[fpc-pascal] Re: Library for network calculation

Jorge Aldo G. de F. Junior jagfj80 at gmail.com
Mon Jul 25 23:52:49 CEST 2011


Some time ago someone asked for a library able to do network calculations.

Here is something that might evolve into such library :

Uses
	Classes,
	SysUtils,
	StrUtils;

Type
	TNetworkIP = Record Case Mode : Boolean Of
		True : (IP1, IP2, IP3, IP4 : Byte);
		False : (IP : LongWord);
	End;

Function StringToIP(aIP : AnsiString): TNetworkIP;
Begin
	Result.Mode := True;
	Result.IP4 := StrToInt(Copy2SymbDel(aIP, '.'));
	Result.IP3 := StrToInt(Copy2SymbDel(aIP, '.'));
	Result.IP2 := StrToInt(Copy2SymbDel(aIP, '.'));
	Result.IP1 := StrToInt(Copy2SymbDel(aIP, '.'));
End;

Function IPToString(aIP : TNetworkIP): String;
Begin
	aIP.Mode := True;
	Result := IntToStr(aIP.IP4) + '.' + IntToStr(aIP.IP3) + '.' +
IntToStr(aIP.IP2) + '.' + IntToStr(aIP.IP1);
End;

Function IPToBits(aIP : TNetworkIP): String;
Begin
	aIP.Mode := True;
	Result := BinStr(aIP.IP4, 8) + BinStr(aIP.IP3, 8) + BinStr(aIP.IP2,
8) + BinStr(aIP.IP1, 8);
End;

Function NetMaskToHostMask(NetMask : TNetworkIP): TNetworkIP;
Begin
	Result.Mode := False;
	NetMask.Mode := False;
	Result.IP := NetMask.IP Xor %11111111111111111111111111111111;
End;

Function HostMaskToNetMask(HostMask : TNetworkIP): TNetworkIP;
Begin
	Result.Mode := False;
	HostMask.Mode := False;
	Result.IP := HostMask.IP Xor %11111111111111111111111111111111;
End;

Function CIDRToNetMask(Bits : Byte): TNetworkIP;
Var
	CurBit : Byte;
	HostMask : TNetworkIP;
Begin
	HostMask.Mode := False;
	HostMask.IP := 0;
	For CurBit := 1 To 32 - Bits Do
		HostMask.IP := HostMask.IP + (1 Shl (CurBit - 1));
	Result := HostMaskToNetMask(HostMask);
End;

Function NetMaskToCIDR(NetMask : TNetworkIP): Byte;
Var
	CurBit : Byte;
Begin
	Result := 0;
	For CurBit := 32 DownTo 1 Do
		If (NetMask.IP And (1 Shl (CurBit - 1))) = (1 Shl (CurBit - 1)) Then
			Result := CurBit;
End;

Function BroadcastOf(IP, NetMask : TNetworkIP): TNetworkIP;
Var
	HostMask : TNetworkIP;
Begin
	HostMask := NetMaskToHostMask(NetMask);
	Result.Mode := False;
	IP.Mode := False;
	HostMask.Mode := False;
	Result.IP := IP.IP Or HostMask.IP;
End;

Function NetworkOf(IP, NetMask : TNetworkIP): TNetworkIP;
Begin
	IP.Mode := False;
	NetMask.Mode := False;
	Result.Mode := False;
	Result.IP := IP.IP And NetMask.IP;
End;

Function HostCount(NetMask : TNetworkIP): LongWord;
Var
	HostMask : TNetworkIP;
Begin
	HostMask := NetMaskToHostMask(NetMask);
	HostMask.Mode := False;
	Result := HostMask.IP + 1;
End;

Function SubNetCount(DefMask, Mask : TNetworkIP): LongWord;
Var
	DefHosts,
	Hosts : LongWord;
Begin
	DefHosts := HostCount(DefMask);
	Hosts := HostCount(Mask);
	Result := DefHosts Div Hosts;
End;

Function IPToRange(IP, NetMask : TNetworkIP): String;
Var
	Net,
	Broad : TNetworkIP;
Begin
	Net := NetworkOf(IP, NetMask);
	Broad := BroadCastOf(IP, NetMask);
	Net.Mode := False;
	Broad.Mode := False;
	Net.IP := Net.IP + 1;
	Broad.IP := Broad.IP - 1;
	Result := IPToString(Net) + '-' + IPToString(Broad);
End;

Function IncSubNet(BaseIP, Mask : TNetworkIP): TNetworkIP;
Var
	HostMask : TNetworkIP;
Begin
	HostMask := NetMaskToHostMask(Mask);
	HostMask.Mode := False;
	HostMask.IP := HostMask.IP + 1;
	BaseIP.Mode := False;
	Result.Mode := False;
	Result.IP := BaseIP.IP + HostMask.IP;
End;

Function HostCountToCIDR(Hosts : LongWord): Byte;
Var
	CurBit : Byte;
	HostMask : TNetworkIP;
	Last1Bit : Byte;
Begin
	HostMask.Mode := False;
	HostMask.IP := Hosts;
	Last1Bit := 0;
	For CurBit := 1 To 32 Do
		If (HostMask.IP And (1 Shl (CurBit - 1))) = (1 Shl (CurBit - 1)) Then
			Last1Bit := CurBit;
	Result := 32 - Last1Bit;
End;

Function HostCountToNetMask(Hosts : LongWord): TNetworkIP;
Begin
	Result := CIDRToNetMask(HostCountToCIDR(Hosts));
End;

Function IsMemberOfSubNet(IP, SubNet : TNetworkIP): Boolean;
Begin
	IP.Mode := False;
	Subnet.Mode := False;
	Result := IP.IP And Subnet.IP = Subnet.IP;
End;

Begin
	WriteLn(IsMemberOfSubNet(StringToIP(ParamStr(1)), StringToIP(Paramstr(2))));
End.

Thats old code, i dont remmember what i was thinking when i wrote that.

It surely could be improved (reformated as a unit, for example).

Could this be added to the FCL ?



More information about the fpc-pascal mailing list