Solved

Reverse DNS Lookup problem

Posted on 2002-04-15
25
291 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
Comment Utility
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
Comment Utility
Hmmm... not really. It should do a reverse DNS lookup similar to the one in TWSocket.
0
 
LVL 7

Expert Comment

by:God_Ares
Comment Utility
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
 

Author Comment

by:DelFreak
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Which will work better, the Async code or the first code you posted?
0
 
LVL 7

Expert Comment

by:God_Ares
Comment Utility
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
Comment Utility
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
Comment Utility
delphi or c?
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 7

Expert Comment

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

Author Comment

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

Expert Comment

by:God_Ares
Comment Utility
shure drop the whole thing...
0
 
LVL 7

Expert Comment

by:God_Ares
Comment Utility
so drop it already.
0
 

Author Comment

by:DelFreak
Comment Utility
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
Comment Utility
God_Ares, any development?
0
 
LVL 7

Expert Comment

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

Author Comment

by:DelFreak
Comment Utility
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
Comment Utility
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
Comment Utility
i read the mail notification was down.. so i hope you'll be notificated.
0
 
LVL 7

Expert Comment

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

Expert Comment

by:sudhakar_koundinya
Comment Utility


 
0
 

Author Comment

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

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

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…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

771 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now