Use getaddrinfo & getnameinfo
[mgsmtp.git] / DNSResolve.pas
index 6e6acff0fdf1865903370d1df911fe0461f2fb53..2ca6439012e325b974d8c3df13b71bd19d6298fa 100644 (file)
@@ -1,5 +1,5 @@
 {
-   Copyright (C) 2010 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This unit is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
 unit DNSResolve;
 
 interface
-uses WinSock, Sockets;
+uses WinSock, Sockets, ctypes;
 
+type
 
-   function ResolveHost(HostName: ansistring): in_addr;
-   function ResolveIP(IP: in_addr): ansistring;
+   PAddrInfo = ^TAddrInfo;
+   TAddrInfo = record
+      ai_flags: cint;
+      ai_family: cint;
+      ai_socktype: cint;
+      ai_protocol: cint;
+      ai_addrlen: size_t;
+      ai_canonname: PChar;
+      ai_addr: PSockAddr;
+      ai_next: PAddrInfo;
+   end;
+
+   TGAIResult = record
+      GAIError: integer;
+      AddrInfo: PAddrInfo;
+   end;
+
+
+   function getaddrinfo(NodeName, ServiceName: PChar; Hints: PAddrInfo; var AddrInfo: PAddrInfo): cint; stdcall;
+      external 'ws2_32.dll' name 'getaddrinfo';
+
+   procedure freeaddrinfo(AddrInfo: PAddrInfo); stdcall;
+      external 'ws2_32.dll' name 'freeaddrinfo';
+
+   function getnameinfo(SockAddr: PSockAddr; SockAddrLength: cuint32; NodeBuffer: PChar; NodeBufferSize: cuint32;
+      ServiceBuffer: PChar; ServiceBufferSize: cuint32; Flags: cint): cint; stdcall;
+      external 'ws2_32.dll' name 'getnameinfo';
+
+   function ResolveHost(HostName: ansistring): TGAIResult;
+   procedure FreeHost(var GAIResult: TGAIResult);
+   function ResolveIP(SockAddr: PSockAddr): ansistring;
 
 
 implementation
 
 
-function ResolveHost(HostName: ansistring): in_addr;
-var
-   HostEnt: PHostEnt;
+function ResolveHost(HostName: ansistring): TGAIResult;
+var hint: TAddrInfo;
+begin
+   FillByte(hint, SizeOf(hint), 0);
+   with hint do begin
+      ai_family:= AF_INET;
+      ai_socktype:= SOCK_STREAM;
+      ai_protocol:= IPPROTO_TCP;
+   end;
+   ResolveHost.GAIError:= getaddrinfo(PChar(HostName), nil, @hint, ResolveHost.AddrInfo);
+end;
+
+procedure FreeHost(var GAIResult: TGAIResult);
 begin
-   HostEnt:= gethostbyname(PChar(HostName));
-   if HostEnt <> nil then
-      ResolveHost.s_addr:= PLongWord(HostEnt^.h_addr_list[0])^
-   else
-      ResolveHost.s_addr:= 0;
+   if GAIResult.AddrInfo <> nil then begin
+      freeaddrinfo(GAIResult.AddrInfo);
+         GAIResult.AddrInfo:= nil;
+   end;
 end;
 
-function ResolveIP(IP: in_addr): ansistring;
+function ResolveIP(SockAddr: PSockAddr): ansistring;
 var
-   HostEnt: PHostEnt;
+   r: integer;
+   NodeBuffer: array[0..255] of char;
 begin
-   HostEnt:= gethostbyaddr(@IP, 4, AF_INET);
-   if HostEnt <> nil then
-      ResolveIP:= HostEnt^.h_name
-   else
-      ResolveIP:= NetAddrToStr(IP);
+   NodeBuffer[0]:= #0;
+   r:= getnameinfo(SockAddr, SizeOf(TSockAddr), @NodeBuffer, SizeOf(NodeBuffer), nil, 0, 0);
+   if r = 0 then ResolveIP:= PChar(@NodeBuffer)
+   else ResolveIP:= NetAddrToStr(SockAddr^.sin_addr);
 end;