Solved

Reverse DNS Lookup problem

Posted on 2002-04-15
25
293 Views
Last Modified: 2010-04-04
Hi experts! I need a function called ReverseDNSLookup similar to the one implemented in TWSocket. But I need it to be a stand-alone function. Could you help me out please! Thanks!
0
Comment
Question by:DelFreak
  • 14
  • 10
25 Comments
 
LVL 7

Expert Comment

by:God_Ares
ID: 6941770
uses WinSock;

function GetHostName(name : string) : string;
var
wsdata : TWSAData;
 he : PHostEnt;
 ip : TInAddr;            
begin
 WSAStartup(MakeWord(1, 1), wsdata);
 ip.S_addr := inet_addr(PChar(name));
 he := gethostbyaddr(@ip.S_un_b, 4, AF_INET);        
 if he<>nil then
   Result := string(he.h_name)
 else
   Result := IntToStr(WSAGetLastError);
 WSACleanup();
end;

function GetIPAddress(name : string) : string;
var wsdata : TWSAData;
   he : PHostEnt;
   ss : pchar;
   ip : TInAddr;
begin
 WSAStartup(MakeWord(1, 1), wsdata);
 he := gethostbyname(pchar(name));
 if he<>nil then
 begin
   ip.S_addr := integer(pointer(he^. h_addr_list^)^);
   ss := inet_ntoa(ip);
   Result := string(ss);
 end;
 WSACleanup();
end;


somthing like this?

0
 

Author Comment

by:DelFreak
ID: 6944151
Hmmm... not really. It should do a reverse DNS lookup similar to the one in TWSocket.
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6944520
you want to make 206.169.61.246 to www.experts-exchange?
so use s:=gethostname('206.169.61.246');.

if it's not then please redefine your question.
0
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 

Author Comment

by:DelFreak
ID: 6947714
Yeah that's the way but I believe TWSocket call WMAsync... I'll post the code later so you can see it. Thanks!
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6948071
so you need a a-synchronic way of resolving ipadresses to hostname's...  oooooohhhh...

you'll see an example at wsocket.pas at line 3382

the function actually comes from a external dll
function WSAAsyncGetHostByName; external winsocket name 'WSAAsyncGetHostByName';  <-hint look at help!

their juggling around with user messages


so you call the function and just wait until your specified message came back.

i you still want an example I’ll make one tomorrow.
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6948089
btw.. it can NEVER be a
stand-alone function.

sice it has 1 procedure to fire the request and one to catch it.
0
 

Author Comment

by:DelFreak
ID: 6949981
Yeah! That's the one. Don't worry, I have a Wndproc that listens for messages. But just in case I need it to be a stanadlone function (without any WndProc function), how can I do it?
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6950062
as i promised:

unit Unit1;
//by god_ares
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   StdCtrls,winsock, ScktComp;

Const
  WM_ASYNCGETHOSTBYNAME     = WM_USER + 1;   //my own messages.
  WM_ASYNCGETHOSTBYADDR     = WM_USER + 2;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Host_to_ip: TButton;
    Edit2: TEdit;
    ClientSocket1: TClientSocket;
    Edit3: TEdit;
    Ip_to_Host: TButton;
    Edit4: TEdit;
    procedure Host_to_ipClick(Sender: TObject);
    procedure Ip_to_HostClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure   WMAsyncGetHostByName(var msg: TMessage); message WM_ASYNCGETHOSTBYNAME;
    procedure   WMAsyncGetHostByAddr(var msg: TMessage); message WM_ASYNCGETHOSTBYADDR;

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
var
    FDnsLookupBuffer    : array [0..MAXGETHOSTSTRUCT] of char;
    FDnsLookupHandle    : THandle;

procedure GetIPList(phe  : PHostEnt; ToList : TStrings);
type
    TaPInAddr = array [0..255] of PInAddr;
    PaPInAddr = ^TaPInAddr;
var
    pptr : PaPInAddr;
    I    : Integer;
begin
    pptr := PaPInAddr(Phe^.h_addr_list);

    I := 0;
    while pptr^[I] <> nil do begin
        ToList.Add(StrPas(inet_ntoa(pptr^[I]^)));
        Inc(I);
    end;
end;


procedure  Tform1.WMAsyncGetHostByName(var msg: TMessage);
var error : integer;
    Phe     : Phostent;
    FDnsResultList : tStringlist;

Begin
  if msg.wParam <> LongInt(FDnsLookupHandle) then Exit;
  FDnsLookupHandle := 0;
  Error := Msg.LParamHi;
  if Error = 0 then
  begin
    FDnsResultList := Tstringlist.create;
    Phe := PHostent(@FDnsLookupBuffer);
    if phe <> nil then
    begin
      GetIpList(Phe, FDnsResultList);
      edit2.text := FDnsResultList.Strings[0];
    end;
    FDnsResultList.free;
  end;
end;

procedure Tform1.WMAsyncGetHostByAddr(var msg: TMessage);
var
    Phe   : Phostent;
    Error : Word;
    s:string;

begin
  if msg.wParam <> LongInt(FDnsLookupHandle) then
      Exit;
  FDnsLookupHandle := 0;
  Error            := Msg.LParamHi;
  if Error = 0 then
  begin
    Phe := PHostent(@FDnsLookupBuffer);
    if phe <> nil then
    begin

      SetLength(s, StrLen(Phe^.h_name));
      StrCopy(@s[1], Phe^.h_name);
      edit4.text:=s;
    end;
  end;

end;


procedure TForm1.Host_to_ipClick(Sender: TObject);
begin
    FDnsLookupHandle   := WSAAsyncGetHostByName(   // <-press f1 for more info! = handy
                              form1.Handle,
                              WM_ASYNCGETHOSTBYNAME,  //<-message to be send back
                              @Edit1.Text[1],
                              @FDnsLookupBuffer,
                              SizeOf(FDnsLookupBuffer));
 if FDnsLookupHandle = 0 then
   showmessage('Error '+IntToStr(WSAGetLastError));


end;

procedure TForm1.Ip_to_HostClick(Sender: TObject);
var
    szAddr : array [0..256] of Char;
    lAddr  : u_long;
    s:string;
begin
    s := Edit3.text;
    StrPCopy(szAddr, s);
    lAddr := inet_addr(szAddr);
    FDnsLookupHandle := WSAAsyncGetHostByAddr( // <-press f1 for more info! = handy
                            form1.Handle,
                            WM_ASYNCGETHOSTBYADDR,  //<-message to be send back
                            PChar(@lAddr), 4, PF_INET,
                            @FDnsLookupBuffer,
                            SizeOf(FDnsLookupBuffer));
 if FDnsLookupHandle = 0 then
   showmessage('Error '+IntToStr(WSAGetLastError));

end;

end.


to your comment:

well i guezz you want to resolve stuff but you don't want to loose any responsivness form your app.

well you simpely can't the nature of a-syncronic resolving is that you don't wait until it returns somthing but you continu doing other stuff. when it's done a message comes and you'll know what happend.

notice: the dnslookup handle can be used for knowing what you ware resolving. (see help for futher details)

what you could do is make a non visual component and make 4 functions (2 groups  ip to host  and host to ip)


resolveHostToIp(Hostname:String);

and

getResolveHostToIp(Hostname:String; var ip:string; var done:boolean,error: boolean);


if you really realy realy want to make just 1 function
and discard the asycronic properties make a non visual component (since you don't want the app to be catching the message but your component)

in pseudo code it would be like

resolve
wait util done resolving
result:

but it's easier to use the function i mentioned above.



0
 

Author Comment

by:DelFreak
ID: 6950251
Which will work better, the Async code or the first code you posted?
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6950304
I would use the first code in a thread or the async stuff, I WOULD NOT use the first code without a thread!

anyway the choice is yours...
0
 

Author Comment

by:DelFreak
ID: 6950607
Hmmm... I'm not sure about that. I'm going to use it in a function I made that filters IP's. The old code used TWSocket but now, I'm modifying it to use Winsock API functions. Hence, this question. Also, the app I'm going to use it on is coded in Pure WinAPI so I can't uses classes. :-(
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6950741
delphi or c?
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6950757
well now you know how it works it shoudn't be all to hard I guezz..
0
 

Author Comment

by:DelFreak
ID: 6950894
I'm using Delphi. If I could post the function, could you help me fix it?
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6950914
shure drop the whole thing...
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6959188
so drop it already.
0
 

Author Comment

by:DelFreak
ID: 6962357
Sorry! Been busy. Anyway, here you go.

function TestIPonFilter(IP, FilterMask: string): string;
var i, x: integer;
  IPList, Temp: TStringList;
  Hostname, CurIP, Filter, FilterIP: string;
  A, B, C, D, AA, BB, CC, DD: string;
  Concluded, Matches: boolean;

  function TestPair(T1, T2: string): boolean;
  var II, IX: integer;
    S1, S2: string;
  begin

    Result := false;

    try
      if StrToInt(T1) = StrToInt(T2) then
      begin
        Result := true;
        Exit;
      end;
    except
    end;

    if T2 = '*' then
    begin
      Result := true;
      Exit;
    end;

    II := Pos('/', T2);

    if II > 1 then
    begin
      S1 := Copy(T2, 1, II - 1);
      S2 := Copy(T2, II + 1, Length(T2));

      II := StrToInt(S1);
      IX := StrToInt(S2);

      if (StrToInt(T1) >= II) and (StrToInt(T1) <= IX) then
      begin
        Result := true;
        Exit;
      end;

    end;

  end;

begin

  if Pos('h', Lowercase(Filtermask)) > 0 then
  begin

    with TWSocket.Create(nil) do
    begin
      ReverseDNSLookup(IP);

      while DNSResult = '' do
        ProcessMessages;

      Hostname := DNSResult;

      Free;
    end;

  end;

  IPList := TStringList.Create;
  Temp := TStringList.Create;
  FilterIP := IP + '.';

  for x := 1 to Length(FilterIP) do
    if FilterIP[x] = '.' then
    begin
      Temp.Add(Filter);
      Filter := '';
    end else
      Filter := Filter + FilterIP[x];

  A := Temp[0];
  B := Temp[1];
  C := Temp[2];
  D := Temp[3];

  CurIP := '';
  Filter := '';

  for i := 1 to Length(FilterMask) do
    if (FilterMask[i] <> ' ') then
      Filter := Filter + FilterMask[i];
  Filter := Filter + ' ';

// Parse Filter
  for i := 1 to Length(Filter) do
  begin
    if ((Filter[i] = '!') or (Filter[i] = '+') or (Filter[i] = '-') or (i = Length(Filter))) and (CurIP <> '') then
    begin
      IPList.Add(CurIP);
      CurIP := '';
    end;
    CurIP := CurIP + Filter[i];
  end;

  Concluded := false;

  for i := 0 to IPList.Count - 1 do
  begin

    if Lowercase(IPList[i][2]) = 'h' then
    begin

      CurIP := Copy(IPList[i], 4, Length(IPList[i]));
      Matches := Pos(CurIP, Hostname) > 0;
      CurIP := CurIP + ' ';

    end else
    begin

      CurIP := IPList[i] + '.';
      Temp.Clear;
      Filter := '';

      for x := 1 to Length(CurIP) do
        if CurIP[x] = '.' then
        begin
          Temp.Add(Filter);
          Filter := '';
        end else
          if (CurIP[x] <> '!') and (CurIP[x] <> '+') and (CurIP[x] <> '-') then
            Filter := Filter + CurIP[x];

      AA := Temp[0];
      BB := Temp[1];
      CC := Temp[2];
      DD := Temp[3];

// Compare IP with filter

      Matches := (TestPair(A, AA) and TestPair(B, BB) and TestPair(C, CC) and TestPair(D, DD));

    end;

    if Matches then
    begin
      Result := IPList[i];
      Concluded := true;
      Break;
    end;

  end;

  if not Concluded then
    Result := '-Unconclusive';

  IPList.Free;
  Temp.Free;

end;
0
 

Author Comment

by:DelFreak
ID: 6974549
God_Ares, any development?
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6974780
could you comment your code... what is it's purpose?
0
 

Author Comment

by:DelFreak
ID: 6974893
It is an IP Filter. It allows/disallows IP's to connect to one of our servers here at work. I used to use TWSocket for the ReverseDNSLookup but I need the code to be more compact and stand-alone so that it can be portable. Hence this question. Hope you can help. Thanks!
0
 
LVL 7

Accepted Solution

by:
God_Ares earned 70 total points
ID: 6976862
unit Unit1;
//by god_ares
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   StdCtrls,winsock, ScktComp;

Const
  WM_ASYNCGETHOSTBYNAME     = WM_USER + 1;

type
  TForm1 = class(TForm)
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure   WMAsyncGetHostByName(var msg: TMessage); message WM_ASYNCGETHOSTBYNAME;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
var
    FDnsLookupBuffer    : array [0..MAXGETHOSTSTRUCT] of char;
    FDnsLookupHandle    : THandle;
    LookupDone : Boolean;
    _ip : string;



procedure  Tform1.WMAsyncGetHostByName(var msg: TMessage);//you need this one

procedure GetIPList(phe  : PHostEnt; ToList : TStrings);
type
    TaPInAddr = array [0..255] of PInAddr;
    PaPInAddr = ^TaPInAddr;
var
    pptr : PaPInAddr;
    I    : Integer;
begin
    pptr := PaPInAddr(Phe^.h_addr_list);

    I := 0;
    while pptr^[I] <> nil do begin
        ToList.Add(StrPas(inet_ntoa(pptr^[I]^)));
        Inc(I);
    end;
end;

var error : integer;
    Phe     : Phostent;
    FDnsResultList : tStringlist;

Begin
  if msg.wParam <> LongInt(FDnsLookupHandle) then Exit;
  FDnsLookupHandle := 0;
  Error := Msg.LParamHi;
  if Error = 0 then
  begin
    FDnsResultList := Tstringlist.create;
    Phe := PHostent(@FDnsLookupBuffer);
    if phe <> nil then
    begin
      GetIpList(Phe, FDnsResultList);
      _ip := FDnsResultList.Strings[0];
      LookupDone := 1=1;
    end;
    FDnsResultList.free;
  end;
end;




procedure TForm1.Button1Click(Sender: TObject);
begin
  //<your code>
  {Find Ip addres with a name}
  ip:='';
  LookupDone := 1=0;

    FDnsLookupHandle   := WSAAsyncGetHostByName(
                              form1.Handle,
                              WM_ASYNCGETHOSTBYNAME,  //<-message to be send back
                              @Edit1.Text[1],
                              @FDnsLookupBuffer,
                              SizeOf(FDnsLookupBuffer)); //go and get it.
  if FDnsLookupHandle = 0 then //maby somthing went wrong?
    showmessage('Error '+IntToStr(WSAGetLastError));

  while Not lookupDone do application.ProcessMessages; //wait...
    edit2.Text := ip;  //gotcha
 //<your code>

end;

function TestIPonFilter(IP, FilterMask: string): string;
var i, x: integer;
 IPList, Temp: TStringList;
 Hostname, CurIP, Filter, FilterIP: string;
 A, B, C, D, AA, BB, CC, DD: string;
 Concluded, Matches: boolean;

 function TestPair(T1, T2: string): boolean;
 var II, IX: integer;
   S1, S2: string;
 begin

   Result := false;

   try
     if StrToInt(T1) = StrToInt(T2) then
     begin
       Result := true;
       Exit;
     end;
   except
   end;

   if T2 = '*' then
   begin
     Result := true;
     Exit;
   end;

   II := Pos('/', T2);

   if II > 1 then
   begin
     S1 := Copy(T2, 1, II - 1);
     S2 := Copy(T2, II + 1, Length(T2));

     II := StrToInt(S1);
     IX := StrToInt(S2);

     if (StrToInt(T1) >= II) and (StrToInt(T1) <= IX) then
     begin
       Result := true;
       Exit;
     end;

   end;

 end;

begin

 if Pos('h', Lowercase(Filtermask)) > 0 then
 begin


  _ip:='';
  LookupDone := 1=0;

    FDnsLookupHandle   := WSAAsyncGetHostByName(
                              form1.Handle,
                              WM_ASYNCGETHOSTBYNAME,  //<-message to be send back
                              @ip[1],
                              @FDnsLookupBuffer,
                              SizeOf(FDnsLookupBuffer)); //go and get it.
  if FDnsLookupHandle = 0 then //maby somthing went wrong?
    showmessage('Error '+IntToStr(WSAGetLastError));

  while Not lookupDone do application.ProcessMessages; //wait...
    hostname := _ip;  //gotcha



 end;

 IPList := TStringList.Create;
 Temp := TStringList.Create;
 FilterIP := IP + '.';

 for x := 1 to Length(FilterIP) do
   if FilterIP[x] = '.' then
   begin
     Temp.Add(Filter);
     Filter := '';
   end else
     Filter := Filter + FilterIP[x];

 A := Temp[0];
 B := Temp[1];
 C := Temp[2];
 D := Temp[3];

 CurIP := '';
 Filter := '';

 for i := 1 to Length(FilterMask) do
   if (FilterMask[i] <> ' ') then
     Filter := Filter + FilterMask[i];
 Filter := Filter + ' ';

// Parse Filter
 for i := 1 to Length(Filter) do
 begin
   if ((Filter[i] = '!') or (Filter[i] = '+') or (Filter[i] = '-') or (i = Length(Filter))) and (CurIP
<> '') then
   begin
     IPList.Add(CurIP);
     CurIP := '';
   end;
   CurIP := CurIP + Filter[i];
 end;

 Concluded := false;

 for i := 0 to IPList.Count - 1 do
 begin

   if Lowercase(IPList[i][2]) = 'h' then
   begin

     CurIP := Copy(IPList[i], 4, Length(IPList[i]));
     Matches := Pos(CurIP, Hostname) > 0;
     CurIP := CurIP + ' ';

   end else
   begin

     CurIP := IPList[i] + '.';
     Temp.Clear;
     Filter := '';

     for x := 1 to Length(CurIP) do
       if CurIP[x] = '.' then
       begin
         Temp.Add(Filter);
         Filter := '';
       end else
         if (CurIP[x] <> '!') and (CurIP[x] <> '+') and (CurIP[x] <> '-') then
           Filter := Filter + CurIP[x];

     AA := Temp[0];
     BB := Temp[1];
     CC := Temp[2];
     DD := Temp[3];

// Compare IP with filter

     Matches := (TestPair(A, AA) and TestPair(B, BB) and TestPair(C, CC) and TestPair(D, DD));

   end;

   if Matches then
   begin
     Result := IPList[i];
     Concluded := true;
     Break;
   end;

 end;

 if not Concluded then
   Result := '-Unconclusive';

 IPList.Free;
 Temp.Free;

end;

end.

didn't test your stuff...
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6990921
i read the mail notification was down.. so i hope you'll be notificated.
0
 
LVL 7

Expert Comment

by:God_Ares
ID: 6995842
i read the mail notification was down.. so i hope you'll be notificated.
0
 
LVL 14

Expert Comment

by:sudhakar_koundinya
ID: 7026108


 
0
 

Author Comment

by:DelFreak
ID: 7171108
Thank you! Sorry it took so long. My Pc got busted. Anyway, thanks again. Great help!
0

Featured Post

Complete VMware vSphere® ESX(i) & Hyper-V Backup

Capture your entire system, including the host, with patented disk imaging integrated with VMware VADP / Microsoft VSS and RCT. RTOs is as low as 15 seconds with Acronis Active Restore™. You can enjoy unlimited P2V/V2V migrations from any source (even from a different hypervisor)

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question