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

Reply via email to