601 lines
17 KiB
Plaintext
601 lines
17 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.4 10/26/2004 10:33:46 PM JPMugaas
|
|
Updated refs.
|
|
|
|
Rev 1.3 2004.02.03 5:44:08 PM czhower
|
|
Name changes
|
|
|
|
Rev 1.2 24/01/2004 19:27:30 CCostelloe
|
|
Cleaned up warnings
|
|
|
|
Rev 1.1 1/21/2004 2:20:26 PM JPMugaas
|
|
InitComponent
|
|
|
|
Rev 1.0 11/13/2002 07:57:46 AM JPMugaas
|
|
}
|
|
|
|
unit IdNetworkCalculator;
|
|
|
|
interface
|
|
|
|
{$i IdCompilerDefines.inc}
|
|
|
|
uses
|
|
Classes,
|
|
IdGlobal,
|
|
IdBaseComponent,
|
|
IdStruct;
|
|
|
|
type
|
|
TNetworkClass = (
|
|
ID_NET_CLASS_A, ID_NET_CLASS_B, ID_NET_CLASS_C, ID_NET_CLASS_D, ID_NET_CLASS_E
|
|
);
|
|
|
|
const
|
|
ID_NC_MASK_LENGTH = 32;
|
|
ID_NETWORKCLASS = ID_NET_CLASS_A;
|
|
|
|
type
|
|
TIdIPAddressType = (IPLocalHost, IPLocalNetwork, IPReserved, IPInternetHost,
|
|
IPPrivateNetwork, IPLoopback, IPMulticast, IPFutureUse, IPGlobalBroadcast);
|
|
|
|
TIpProperty = class(TPersistent)
|
|
protected
|
|
FReadOnly: Boolean;
|
|
FBitArray: array[0..31] of Boolean;
|
|
FValue: array[0..3] of Byte;
|
|
FOnChange: TNotifyEvent;
|
|
function GetAddressType: TIdIPAddressType;
|
|
function GetAsBinaryString: String;
|
|
function GetAsDoubleWord: UInt32;
|
|
function GetAsString: String;
|
|
function GetBit(Index: Byte): Boolean;
|
|
function GetByte(Index: Integer): Byte;
|
|
procedure SetAsBinaryString(const Value: String);
|
|
procedure SetAsDoubleWord(const Value: UInt32);
|
|
procedure SetAsString(const Value: String);
|
|
procedure SetBit(Index: Byte; const Value: Boolean);
|
|
procedure SetByte(Index: Integer; const Value: Byte);
|
|
//
|
|
property IsReadOnly: Boolean read FReadOnly write FReadOnly default False;
|
|
public
|
|
constructor Create; virtual;
|
|
destructor Destroy; override;
|
|
//
|
|
procedure SetAll(One, Two, Three, Four: Byte); virtual;
|
|
procedure Assign(Source: TPersistent); override;
|
|
//
|
|
property Bits[Index: Byte]: Boolean read GetBit write SetBit;
|
|
property AddressType: TIdIPAddressType read GetAddressType;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
published
|
|
property Byte1: Byte index 0 read GetByte write SetByte stored False;
|
|
property Byte2: Byte index 1 read GetByte write SetByte stored False;
|
|
property Byte3: Byte index 2 read GetByte write SetByte stored False;
|
|
property Byte4: Byte index 3 read GetByte write SetByte stored False;
|
|
property AsDoubleWord: UInt32 read GetAsDoubleWord write SetAsDoubleWord stored False;
|
|
property AsBinaryString: String read GetAsBinaryString write SetAsBinaryString stored False;
|
|
property AsString: String read GetAsString write SetAsString;
|
|
end;
|
|
|
|
TIdNetworkCalculator = class(TIdBaseComponent)
|
|
protected
|
|
FListIP: TStrings;
|
|
FNetworkMaskLength: UInt32;
|
|
FNetworkMask: TIpProperty;
|
|
FNetworkAddress: TIpProperty;
|
|
FNetworkClass: TNetworkClass;
|
|
FOnChange: TNotifyEvent;
|
|
FOnGenIPList: TNotifyEvent;
|
|
procedure FillIPList;
|
|
function GetNetworkClassAsString: String;
|
|
function GetIsAddressRoutable: Boolean;
|
|
function GetListIP: TStrings;
|
|
procedure SetNetworkAddress(const Value: TIpProperty);
|
|
procedure SetNetworkMask(const Value: TIpProperty);
|
|
procedure SetNetworkMaskLength(const Value: UInt32);
|
|
procedure NetMaskChanged(Sender: TObject);
|
|
procedure NetAddressChanged(Sender: TObject);
|
|
procedure InitComponent; override;
|
|
public
|
|
destructor Destroy; override;
|
|
function IsAddressInNetwork(const Address: String): Boolean;
|
|
function NumIP: UInt32;
|
|
function StartIP: String;
|
|
function EndIP: String;
|
|
//
|
|
property ListIP: TStrings read GetListIP;
|
|
property NetworkClass: TNetworkClass read FNetworkClass;
|
|
property NetworkClassAsString: String read GetNetworkClassAsString;
|
|
property IsAddressRoutable: Boolean read GetIsAddressRoutable;
|
|
published
|
|
property NetworkAddress: TIpProperty read FNetworkAddress write SetNetworkAddress;
|
|
property NetworkMask: TIpProperty read FNetworkMask write SetNetworkMask;
|
|
property NetworkMaskLength: UInt32 read FNetworkMaskLength write SetNetworkMaskLength
|
|
default ID_NC_MASK_LENGTH;
|
|
property OnGenIPList: TNotifyEvent read FOnGenIPList write FOnGenIPList;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
IdException, IdGlobalProtocols, IdResourceStringsProtocols, IdStack, SysUtils;
|
|
|
|
function MakeLongWordIP(const One, Two, Three, Four: Byte): UInt32;
|
|
begin
|
|
Result := (UInt32(One) shl 24) or (UInt32(Two) shl 16) or (UInt32(Three) shl 8) or UInt32(Four);
|
|
end;
|
|
|
|
procedure BreakupLongWordIP(const Value: UInt32; var One, Two, Three, Four: Byte);
|
|
begin
|
|
One := Byte((Value and $FF000000) shr 24);
|
|
Two := Byte((Value and $00FF0000) shr 16);
|
|
Three := Byte((Value and $0000FF00) shr 8);
|
|
Four := Byte(Value and $000000FF);
|
|
end;
|
|
|
|
function StrToIP(const Value: string): UInt32;
|
|
var
|
|
strBuffers: Array [0..3] of String;
|
|
cardBuffers: Array[0..3] of UInt32;
|
|
StrWork: String;
|
|
I: Integer;
|
|
begin
|
|
StrWork := Value;
|
|
// Separate the strings
|
|
strBuffers[0] := Fetch(StrWork, '.', True); {Do not Localize}
|
|
strBuffers[1] := Fetch(StrWork, '.', True); {Do not Localize}
|
|
strBuffers[2] := Fetch(StrWork, '.', True); {Do not Localize}
|
|
strBuffers[3] := StrWork;
|
|
try
|
|
for I := 0 to 3 do begin
|
|
cardBuffers[I] := IndyStrToInt(strBuffers[I]);
|
|
end;
|
|
except
|
|
IndyRaiseOuterException(EIdException.CreateFmt(RSNETCALInvalidIPString, [Value]));
|
|
end;
|
|
// range check
|
|
for I := 0 to 3 do begin
|
|
if not (cardBuffers[I] in [0..255]) then begin
|
|
raise EIdException.CreateFmt(RSNETCALInvalidIPString, [Value]);
|
|
end;
|
|
end;
|
|
Result := MakeLongWordIP(cardBuffers[0], cardBuffers[1], cardBuffers[2], cardBuffers[3]);
|
|
end;
|
|
|
|
{ TIdNetworkCalculator }
|
|
|
|
procedure TIdNetworkCalculator.InitComponent;
|
|
begin
|
|
inherited InitComponent;
|
|
FNetworkMask := TIpProperty.Create;
|
|
FNetworkMask.OnChange := NetMaskChanged;
|
|
FNetworkAddress := TIpProperty.Create;
|
|
FNetworkAddress.OnChange := NetAddressChanged;
|
|
FListIP := TStringList.Create;
|
|
FNetworkClass := ID_NETWORKCLASS;
|
|
NetworkMaskLength := ID_NC_MASK_LENGTH;
|
|
end;
|
|
|
|
destructor TIdNetworkCalculator.Destroy;
|
|
begin
|
|
FreeAndNil(FNetworkMask);
|
|
FreeAndNil(FNetworkAddress);
|
|
FreeAndNil(FListIP);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.FillIPList;
|
|
var
|
|
i: UInt32;
|
|
BaseIP: UInt32;
|
|
LByte1, LByte2, LByte3, LByte4: Byte;
|
|
begin
|
|
if FListIP.Count = 0 then
|
|
begin
|
|
// prevent to start a long loop in the IDE (will lock delphi)
|
|
if IsDesignTime and (NumIP > 1024) then begin
|
|
FListIP.text := IndyFormat(RSNETCALConfirmLongIPList, [NumIP]);
|
|
end else
|
|
begin
|
|
BaseIP := NetworkAddress.AsDoubleWord and NetworkMask.AsDoubleWord;
|
|
// Lock the list so we won't be "repainting" the whole time... {Do not Localize}
|
|
FListIP.BeginUpdate;
|
|
try
|
|
FListIP.Capacity := NumIP;
|
|
for i := 1 to (NumIP - 1) do
|
|
begin
|
|
Inc(BaseIP);
|
|
BreakupLongWordIP(BaseIP, LByte1, LByte2, LByte3, LByte4);
|
|
FListIP.Append(IndyFormat('%d.%d.%d.%d', [LByte1, LByte2, LByte3, LByte4])); {Do not Localize}
|
|
end;
|
|
finally
|
|
FListIP.EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TIdNetworkCalculator.GetListIP: TStrings;
|
|
begin
|
|
FillIPList;
|
|
Result := FListIP;
|
|
end;
|
|
|
|
function TIdNetworkCalculator.IsAddressInNetwork(const Address: String): Boolean;
|
|
begin
|
|
Result := (StrToIP(Address) and NetworkMask.AsDoubleWord) = (NetworkAddress.AsDoubleWord and NetworkMask.AsDoubleWord);
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.NetAddressChanged(Sender: TObject);
|
|
var
|
|
sBuffer: String;
|
|
begin
|
|
FListIP.Clear;
|
|
sBuffer := NetworkAddress.AsBinaryString;
|
|
// RFC 1365
|
|
if TextStartsWith(sBuffer, '0') then begin {Do not Localize}
|
|
fNetworkClass := ID_NET_CLASS_A;
|
|
end
|
|
else if TextStartsWith(sBuffer, '10') then begin {Do not Localize}
|
|
fNetworkClass := ID_NET_CLASS_B;
|
|
end
|
|
else if TextStartsWith(sBuffer, '110') then begin {Do not Localize}
|
|
fNetworkClass := ID_NET_CLASS_C;
|
|
end
|
|
// Network class D is reserved for multicast
|
|
else if TextStartsWith(sBuffer, '1110') then begin {Do not Localize}
|
|
fNetworkClass := ID_NET_CLASS_D;
|
|
end
|
|
// network class E is reserved and shouldn't be used {Do not Localize}
|
|
else {if TextStartsWith(sBuffer, '1111') then} begin {Do not Localize}
|
|
fNetworkClass := ID_NET_CLASS_E;
|
|
end;
|
|
if Assigned(FOnChange) then begin
|
|
FOnChange(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.NetMaskChanged(Sender: TObject);
|
|
var
|
|
sBuffer: string;
|
|
InitialMaskLength: UInt32;
|
|
begin
|
|
FListIP.Clear;
|
|
InitialMaskLength := FNetworkMaskLength;
|
|
// A network mask MUST NOT contains holes.
|
|
sBuffer := FNetworkMask.AsBinaryString;
|
|
while TextStartsWith(sBuffer, '1') do begin {Do not Localize}
|
|
Delete(sBuffer, 1, 1);
|
|
end;
|
|
if IndyPos('1', sBuffer) > 0 then {Do not Localize}
|
|
begin
|
|
NetworkMaskLength := InitialMaskLength;
|
|
raise EIdException.Create(RSNETCALCInvalidNetworkMask); // 'Invalid network mask' {Do not Localize}
|
|
end;
|
|
// set the net mask length
|
|
NetworkMaskLength := 32 - Length(sBuffer);
|
|
if Assigned(FOnChange) then begin
|
|
FOnChange(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.SetNetworkAddress(const Value: TIpProperty);
|
|
begin
|
|
FNetworkAddress.Assign(Value);
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.SetNetworkMask(const Value: TIpProperty);
|
|
begin
|
|
FNetworkMask.Assign(Value);
|
|
end;
|
|
|
|
procedure TIdNetworkCalculator.SetNetworkMaskLength(const Value: UInt32);
|
|
var
|
|
LBuffer, LValue: UInt32;
|
|
begin
|
|
if Value <= 32 then begin
|
|
LValue := Value;
|
|
end else begin
|
|
LValue := 32;
|
|
end;
|
|
if FNetworkMaskLength <> LValue then
|
|
begin
|
|
FNetworkMaskLength := LValue;
|
|
if Value > 0 then begin
|
|
LBuffer := High(UInt32) shl (32 - LValue);
|
|
end else begin
|
|
LBuffer := 0;
|
|
end;
|
|
FNetworkMask.AsDoubleWord := LBuffer;
|
|
end;
|
|
end;
|
|
|
|
function TIdNetworkCalculator.GetNetworkClassAsString: String;
|
|
const
|
|
sClasses: array[TNetworkClass] of String = ('A', 'B', 'C', 'D','E'); {Do not Localize}
|
|
begin
|
|
Result := sClasses[FNetworkClass];
|
|
end;
|
|
|
|
function TIdNetworkCalculator.GetIsAddressRoutable: Boolean;
|
|
begin
|
|
// RFC 1918
|
|
Result := not (
|
|
(FNetworkAddress.Byte1 = 10) or
|
|
((FNetworkAddress.Byte1 = 172) and (FNetworkAddress.Byte2 in [16..31])) or
|
|
((FNetworkAddress.Byte1 = 192) and (FNetworkAddress.Byte2 = 168))
|
|
);
|
|
end;
|
|
|
|
function TIdNetworkCalculator.EndIP: String;
|
|
var
|
|
IP: UInt32;
|
|
LByte1, LByte2, LByte3, LByte4: Byte;
|
|
begin
|
|
IP := (NetworkAddress.AsDoubleWord and NetworkMask.AsDoubleWord) + (NumIP - 1);
|
|
BreakupLongWordIP(IP, LByte1, LByte2, LByte3, LByte4);
|
|
Result := IndyFormat('%d.%d.%d.%d', [LByte1, LByte2, LByte3, LByte4]); {Do not Localize}
|
|
end;
|
|
|
|
function TIdNetworkCalculator.NumIP: UInt32;
|
|
begin
|
|
Result := 1 shl (32 - NetworkMaskLength);
|
|
end;
|
|
|
|
function TIdNetworkCalculator.StartIP: String;
|
|
var
|
|
IP: UInt32;
|
|
LByte1, LByte2, LByte3, LByte4: Byte;
|
|
begin
|
|
IP := NetworkAddress.AsDoubleWord and NetworkMask.AsDoubleWord;
|
|
BreakupLongWordIP(IP, LByte1, LByte2, LByte3, LByte4);
|
|
Result := IndyFormat('%d.%d.%d.%d', [LByte1, LByte2, LByte3, LByte4]); {Do not Localize}
|
|
end;
|
|
|
|
{ TIpProperty }
|
|
|
|
constructor TIpProperty.Create;
|
|
begin
|
|
inherited Create;
|
|
FValue[0] := $0;
|
|
FValue[1] := $0;
|
|
FValue[2] := $0;
|
|
FValue[3] := $0;
|
|
end;
|
|
|
|
destructor TIpProperty.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIpProperty.Assign(Source: TPersistent);
|
|
var
|
|
LSource: TIpProperty;
|
|
begin
|
|
if Source is TIpProperty then
|
|
begin
|
|
LSource := TIpProperty(Source);
|
|
SetAll(LSource.Byte1, LSource.Byte2, LSource.Byte3, LSource.Byte4);
|
|
end else begin
|
|
inherited Assign(Source);
|
|
end;
|
|
end;
|
|
|
|
function TIpProperty.GetBit(Index: Byte): boolean;
|
|
begin
|
|
Result := FBitArray[index];
|
|
end;
|
|
|
|
procedure TIpProperty.SetAll(One, Two, Three, Four: Byte);
|
|
var
|
|
i, j: Integer;
|
|
begin
|
|
if (FValue[0] <> One) or (FValue[1] <> Two) or (FValue[2] <> Three) or (FValue[3] <> Four) then
|
|
begin
|
|
FValue[0] := One;
|
|
FValue[1] := Two;
|
|
FValue[2] := Three;
|
|
FValue[3] := Four;
|
|
// set the binary array
|
|
for i := 0 to 3 do begin
|
|
for j := 0 to 7 do begin
|
|
FBitArray[(8*i)+j] := (FValue[i] and (1 shl (7-j))) <> 0;
|
|
end;
|
|
end;
|
|
if Assigned(FOnChange) then begin
|
|
FOnChange(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TIpProperty.GetAsBinaryString: String;
|
|
var
|
|
i : Integer;
|
|
{$IFDEF STRING_IS_IMMUTABLE}
|
|
LSB: TIdStringBuilder;
|
|
{$ENDIF}
|
|
begin
|
|
// get the binary string
|
|
{$IFDEF STRING_IS_IMMUTABLE}
|
|
LSB := TIdStringBuilder.Create(32);
|
|
{$ELSE}
|
|
SetLength(Result, 32);
|
|
{$ENDIF}
|
|
for i := 1 to 32 do
|
|
begin
|
|
if FBitArray[i-1] then begin
|
|
{$IFDEF STRING_IS_IMMUTABLE}
|
|
LSB.Append(Char('1')); {Do not Localize}
|
|
{$ELSE}
|
|
Result[i] := '1'; {Do not Localize}
|
|
{$ENDIF}
|
|
end else begin
|
|
{$IFDEF STRING_IS_IMMUTABLE}
|
|
LSB.Append(Char('0')); {Do not Localize}
|
|
{$ELSE}
|
|
Result[i] := '0'; {Do not Localize}
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
{$IFDEF STRING_IS_IMMUTABLE}
|
|
Result := LSB.ToString;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function TIpProperty.GetAsDoubleWord: UInt32;
|
|
begin
|
|
Result := MakeLongWordIP(FValue[0], FValue[1], FValue[2], FValue[3]);
|
|
end;
|
|
|
|
function TIpProperty.GetAsString: String;
|
|
begin
|
|
// Set the string
|
|
Result := IndyFormat('%d.%d.%d.%d', [FValue[0], FValue[1], FValue[2], FValue[3]]); {Do not Localize}
|
|
end;
|
|
|
|
procedure TIpProperty.SetAsBinaryString(const Value: String);
|
|
var
|
|
i: Integer;
|
|
NewIP: UInt32;
|
|
begin
|
|
if IsReadOnly then begin
|
|
Exit;
|
|
end;
|
|
if Length(Value) <> 32 then begin
|
|
raise EIdException.Create(RSNETCALCInvalidValueLength) // 'Invalid value length: Should be 32.' {Do not Localize}
|
|
end;
|
|
if not TextIsSame(Value, AsBinaryString) then
|
|
begin
|
|
NewIP := 0;
|
|
for i := 1 to 32 do
|
|
begin
|
|
if Value[i] <> '0' then begin {Do not Localize}
|
|
NewIP := NewIP or (1 shl (32 - i));
|
|
end;
|
|
end;
|
|
SetAsDoubleWord(NewIP);
|
|
end;
|
|
end;
|
|
|
|
function TIpProperty.GetByte(Index: Integer): Byte;
|
|
begin
|
|
Result := FValue[Index];
|
|
end;
|
|
|
|
procedure TIpProperty.SetAsDoubleWord(const Value: UInt32);
|
|
var
|
|
LByte1, LByte2, LByte3, LByte4: Byte;
|
|
begin
|
|
if not IsReadOnly then
|
|
begin
|
|
BreakupLongWordIP(Value, LByte1, LByte2, LByte3, LByte4);
|
|
SetAll(LByte1, LByte2, LByte3, LByte4);
|
|
end;
|
|
end;
|
|
|
|
procedure TIpProperty.SetAsString(const Value: String);
|
|
begin
|
|
SetAsDoubleWord(StrToIP(Value));
|
|
end;
|
|
|
|
procedure TIpProperty.SetBit(Index: Byte; const Value: Boolean);
|
|
var
|
|
ByteIndex: Integer;
|
|
BitValue: Byte;
|
|
begin
|
|
if (not IsReadOnly) and (FBitArray[Index] <> Value) then
|
|
begin
|
|
FBitArray[Index] := Value;
|
|
ByteIndex := Index div 8;
|
|
BitValue := Byte(1 shl (7-(Index mod 8)));
|
|
if Value then begin
|
|
FValue[ByteIndex] := FValue[ByteIndex] or BitValue;
|
|
end else begin
|
|
FValue[ByteIndex] := FValue[ByteIndex] and not BitValue;
|
|
end;
|
|
if Assigned(OnChange) then begin
|
|
OnChange(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TIpProperty.SetByte(Index: Integer; const Value: Byte);
|
|
begin
|
|
if (not IsReadOnly) and (GetByte(Index) <> Value) then
|
|
begin
|
|
case Index of
|
|
0: SetAll(Value, Byte2, Byte3, Byte4);
|
|
1: SetAll(Byte1, Value, Byte3, Byte4);
|
|
2: SetAll(Byte1, Byte2, Value, Byte4);
|
|
3: SetAll(Byte1, Byte2, Byte3, Value);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TIpProperty.GetAddressType: TIdIPAddressType;
|
|
// based on http://www.ora.com/reference/dictionary/terms/I/IP_Address.htm
|
|
begin
|
|
Result := IPInternetHost;
|
|
case Byte1 of
|
|
{localhost or local network}
|
|
0 : if AsDoubleWord = 0 then begin
|
|
Result := IPLocalHost;
|
|
end else begin
|
|
Result := IPLocalNetwork;
|
|
end;
|
|
{Private network allocations}
|
|
10 : Result := IPPrivateNetwork;
|
|
172 : if Byte2 = 16 then begin
|
|
Result := IPPrivateNetwork;
|
|
end;
|
|
192 : if Byte2 = 168 then begin
|
|
Result := IPPrivateNetwork;
|
|
end
|
|
else if (Byte2 = 0) and (Byte3 = 0) then begin
|
|
Result := IPReserved;
|
|
end;
|
|
{loopback}
|
|
127 : Result := IPLoopback;
|
|
255 : if AsDoubleWord = $FFFFFFFF then begin
|
|
Result := IPGlobalBroadcast;
|
|
end else begin
|
|
Result := IPFutureUse;
|
|
end;
|
|
{Reserved}
|
|
128 : if Byte2 = 0 then begin
|
|
Result := IPReserved;
|
|
end;
|
|
191 : if (Byte2 = 255) and (Byte3 = 255) then begin
|
|
Result := IPReserved;
|
|
end;
|
|
223 : if (Byte2 = 255) and (Byte3 = 255) then begin
|
|
Result := IPReserved;
|
|
end;
|
|
{Multicast}
|
|
224..239: Result := IPMulticast;
|
|
{Future Use}
|
|
240..254: Result := IPFutureUse;
|
|
end;
|
|
end;
|
|
|
|
end.
|