Hi Angus,
Thanks for the given information, I think I've been able to implement
this correctly.
For future reference I've included the source of the unit which I use
now. Angus, maybe you can look it through very briefly to see if I
messed up anywhere :p
I realize it uses a lot of features only available in latest Delphi
versions (dotted unit names, generics, class vars, etc), but I think
it's easy to extract the interesting parts if required.
Since all is based on class vars and class functions there is no need to
create and destroy objects.
Thanks!
unit Network.Subnets;
interface
uses
Winapi.Windows, System.Generics.Collections;
type TNetworkSubnets = class(TObject)
private
const REFRESH_TIME_SECONDS = 60; // this constants defines after
how many seconds we want to refresh
// the adapter list (adapter
got connected, config changed, etc
type RNetworkRange = record
MinHost: DWord;
MaxHost: DWord;
end;
private
class var fLastRefreshTimestamp: TDateTime;
class var fNetworkRanges: TArray<RNetworkRange>;
class function IPToHBO(IP: string): DWORD;
class procedure RefreshNetworkRanges;
public
class function InCurrentSubnets(IP: string): boolean;
end;
implementation
uses
IPHelper, OverbyteIcsWSocket, System.DateUtils, System.SysUtils;
{ TNetworkSubnets }
class function TNetworkSubnets.InCurrentSubnets(IP: string): boolean;
var IP_HBO: DWORD;
NetworkRange: RNetworkRange;
begin
result := false;
if (fLastRefreshTimestamp = 0) or (SecondsBetween(Now(),
fLastRefreshTimestamp) > REFRESH_TIME_SECONDS) then
begin
RefreshNetworkRanges();
fLastRefreshTimestamp := Now();
end;
IP_HBO := IPToHBO(IP);
for NetworkRange in fNetworkRanges do
if (IP_HBO >= NetworkRange.MinHost) and (IP_HBO <=
NetworkRange.MaxHost) then
exit(true);
end;
class function TNetworkSubnets.IPToHBO(IP: string): DWORD;
// converts given IP string to host byte order
begin
result := WSocket_ntohl(WSocket_inet_addr(ansistring(IP)));
end;
class procedure TNetworkSubnets.RefreshNetworkRanges;
var NrOfAdapters: integer;
Adapters: TAdaptorRows;
Adapter: TAdaptorInfo;
i, j: integer;
IP, Mask: DWORD;
begin
IpHlpAdaptersInfo(NrOfAdapters, Adapters);
// get quick count of maximum number of network ranges (adapters * ip
addresses per adapter)
i := 0;
for Adapter in Adapters do
inc(i, Adapter.IPAddressTot);
SetLength(fNetworkRanges, i);
j := 0;
for Adapter in Adapters do
for i := 0 to Adapter.IPAddressTot - 1 do
begin
// check if there is some valid ip for this adapter
if (Adapter.IPAddressList[i] = '0.0.0.0') or (Adapter.IPMaskList[i]
= '0.0.0.0') then
continue;
IP := IPToHBO(Adapter.IPAddressList[i]);
Mask := IPToHBO(Adapter.IPMaskList[i]);
fNetworkRanges[j].MinHost := IP and Mask;
fNetworkRanges[j].MaxHost := fNetworkRanges[j].MinHost or (not Mask);
inc(j);
end;
// now trunc the array to the actual number of network ranges
SetLength(fNetworkRanges, j);
end;
end.
usage:
if TNetworkSubnets.InCurrentSubnets('192.168.1.2') then
On 16-4-2013 12:25, Angus Robertson - Magenta Systems Ltd wrote:
I'm trying to figure out if a given ip address is in any of the
subnets I'm connected to
I assume I need to iterate through all connected NICS, and
calculate the size and location of that specific subnet using the
ip and netmask for that connection, and then see if given ip
address falls in that subnet?
The Internet Protocol Helper Component will get you the assigned IP
addresses and masks:
http://www.magsys.co.uk/delphi/magiphlp.asp
Can anybody give me a pointer in the right direction please? Is
there any api (or ics tool) which can do the subnet calculation for
me?
The trick with IP addresses is always to work with 32-bit unsigned double
words, AND and ORs give you the subnet limits, then it's simple range
comparisons. Make sure the endian order is reversed for Intel.
Angus
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be