Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 304
  • Last Modified:

Reverse DNS Lookup problem

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
DelFreak
Asked:
DelFreak
  • 14
  • 10
1 Solution
 
God_AresCommented:
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
 
DelFreakAuthor Commented:
Hmmm... not really. It should do a reverse DNS lookup similar to the one in TWSocket.
0
 
God_AresCommented:
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
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
DelFreakAuthor Commented:
Yeah that's the way but I believe TWSocket call WMAsync... I'll post the code later so you can see it. Thanks!
0
 
God_AresCommented:
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
 
God_AresCommented:
btw.. it can NEVER be a
stand-alone function.

sice it has 1 procedure to fire the request and one to catch it.
0
 
DelFreakAuthor Commented:
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
 
God_AresCommented:
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
 
DelFreakAuthor Commented:
Which will work better, the Async code or the first code you posted?
0
 
God_AresCommented:
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
 
DelFreakAuthor Commented:
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
 
God_AresCommented:
delphi or c?
0
 
God_AresCommented:
well now you know how it works it shoudn't be all to hard I guezz..
0
 
DelFreakAuthor Commented:
I'm using Delphi. If I could post the function, could you help me fix it?
0
 
God_AresCommented:
shure drop the whole thing...
0
 
God_AresCommented:
so drop it already.
0
 
DelFreakAuthor Commented:
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
 
DelFreakAuthor Commented:
God_Ares, any development?
0
 
God_AresCommented:
could you comment your code... what is it's purpose?
0
 
DelFreakAuthor Commented:
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
 
God_AresCommented:
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
 
God_AresCommented:
i read the mail notification was down.. so i hope you'll be notificated.
0
 
God_AresCommented:
i read the mail notification was down.. so i hope you'll be notificated.
0
 
sudhakar_koundinyaCommented:


 
0
 
DelFreakAuthor Commented:
Thank you! Sorry it took so long. My Pc got busted. Anyway, thanks again. Great help!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 14
  • 10
Tackle projects and never again get stuck behind a technical roadblock.
Join Now