FIX: FTP - ResolveName under macOS (issue #1604)

(cherry picked from commit 2aa9fe2f5a)
This commit is contained in:
Alexander Koblov 2024-10-27 18:14:02 +03:00
commit 536fd18063

View file

@ -446,6 +446,86 @@ function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Wor
{==============================================================================}
implementation
uses
InitC;
{$if defined(LINUX) or defined(OPENBSD)}
{$define FIRST_ADDR_THEN_CANONNAME}
{$elseif defined(FREEBSD) or defined(NETBSD) or defined(DRAGONFLY) or defined(SOLARIS) or defined(ANDROID) or defined(DARWIN)}
{$define FIRST_CANONNAME_THEN_ADDR}
{$else}
{$error fatal 'Please consult the netdb.h file for your system to determine the order of ai_addr and ai_canonname'}
{$endif}
{$push}{$packrecords c}
type
PAddrInfo = ^addrinfo;
addrinfo = record
ai_flags: cint; {* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST *}
ai_family: cint; {* PF_xxx *}
ai_socktype: cint; {* SOCK_xxx *}
ai_protocol: cint; {* 0 or IPPROTO_xxx for IPv4 and IPv6 *}
ai_addrlen: TSockLen; {* length of ai_addr *}
{$ifdef FIRST_CANONNAME_THEN_ADDR}
ai_canonname: PAnsiChar; {* canonical name for hostname *}
ai_addr: psockaddr; {* binary address *}
{$endif}
{$ifdef FIRST_ADDR_THEN_CANONNAME}
ai_addr: psockaddr; {* binary address *}
ai_canonname: PAnsiChar; {* canonical name for hostname *}
{$endif}
ai_next: PAddrInfo; {* next structure in linked list *}
end;
TAddrInfo = addrinfo;
PPAddrInfo = ^PAddrInfo;
{$pop}
function getaddrinfo(name, service: PAnsiChar; hints: PAddrInfo; res: PPAddrInfo): cint; cdecl; external clib;
procedure freeaddrinfo(ai: PAddrInfo); cdecl; external clib;
function ResolveName(const HostName: String; Addresses: Pointer; MaxAddresses, Family: Integer): Integer; overload;
var
hints: TAddrInfo;
res, ai: PAddrInfo;
begin
Result:= -1;
if MaxAddresses = 0 then Exit;
res:= nil;
hints:= Default(TAddrInfo);
hints.ai_family:= Family;
hints.ai_socktype:= SOCK_STREAM;
if (getaddrinfo(PAnsiChar(HostName), nil, @hints, @res) <> 0) or (res = nil) then
Exit;
ai:= res;
Result:= 0;
repeat
if ai^.ai_family = Family then
begin
if Family = AF_INET then
begin
Move(PInetSockAddr(ai^.ai_addr)^.sin_addr, Addresses^, SizeOf(TInAddr));
Inc(PInAddr(Addresses));
end
else begin
Move(PInetSockAddr6(ai^.ai_addr)^.sin6_addr, Addresses^, SizeOf(TIn6Addr));
Inc(PIn6Addr(Addresses));
end;
Inc(Result);
end;
ai:= ai^.ai_next;
until (ai = nil) or (Result >= MaxAddresses);
freeaddrinfo(res);
end;
function ResolveName(HostName: String; var Addresses: array of THostAddr): Integer; overload;
begin
Result:= ResolveName(HostName, @Addresses, Length(Addresses), AF_INET);
end;
function ResolveName6(HostName: String; var Addresses: array of THostAddr6): Integer;
begin
Result:= ResolveName(HostName, @Addresses, Length(Addresses), AF_INET6);
end;
function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
begin