?
Solved

Reverse DNS Lookup problem

Posted on 2002-04-15
25
Medium Priority
?
298 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

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 280 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

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month14 days, 8 hours left to enroll

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