27913b0b8bf15f0e0e8c9da840ca3ca2a0c3ca20
[mgsmtp.git] / DNSResolve.pas
1 {
2 Copyright (C) 2010-2018 MegaBrutal
3
4 This unit is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This unit is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 }
17
18
19 {$MODE FPC}
20
21 unit DNSResolve;
22
23 interface
24 uses WinSock, Sockets, ctypes;
25
26 type
27
28 PAddrInfo = ^TAddrInfo;
29 TAddrInfo = record
30 ai_flags: cint;
31 ai_family: cint;
32 ai_socktype: cint;
33 ai_protocol: cint;
34 ai_addrlen: size_t;
35 ai_canonname: PChar;
36 ai_addr: PSockAddr;
37 ai_next: PAddrInfo;
38 end;
39
40 TGAIResult = record
41 GAIError: integer;
42 AddrInfo: PAddrInfo;
43 end;
44
45
46 function getaddrinfo(NodeName, ServiceName: PChar; Hints: PAddrInfo; var AddrInfo: PAddrInfo): cint; stdcall;
47 external 'ws2_32.dll' name 'getaddrinfo';
48
49 procedure freeaddrinfo(AddrInfo: PAddrInfo); stdcall;
50 external 'ws2_32.dll' name 'freeaddrinfo';
51
52 function getnameinfo(SockAddr: PSockAddr; SockAddrLength: cuint32; NodeBuffer: PChar; NodeBufferSize: cuint32;
53 ServiceBuffer: PChar; ServiceBufferSize: cuint32; Flags: cint): cint; stdcall;
54 external 'ws2_32.dll' name 'getnameinfo';
55
56 function ResolveHost(HostName: ansistring; Family: cint): TGAIResult;
57 procedure FreeHost(var GAIResult: TGAIResult);
58 function ResolveIP(AddrInfo: PAddrInfo): ansistring; overload;
59 function ResolveIP(SockAddr: PSockAddr): ansistring; overload;
60 function IPToStr(SockAddr: PSockAddr): ansistring;
61
62
63 implementation
64
65
66 function ResolveHost(HostName: ansistring; Family: cint): TGAIResult;
67 var hint: TAddrInfo;
68 begin
69 FillByte(hint, SizeOf(hint), 0);
70 with hint do begin
71 ai_family:= Family;
72 ai_socktype:= SOCK_STREAM;
73 ai_protocol:= IPPROTO_TCP;
74 end;
75 ResolveHost.GAIError:= getaddrinfo(PChar(HostName), nil, @hint, ResolveHost.AddrInfo);
76 end;
77
78 procedure FreeHost(var GAIResult: TGAIResult);
79 begin
80 if GAIResult.AddrInfo <> nil then begin
81 freeaddrinfo(GAIResult.AddrInfo);
82 GAIResult.AddrInfo:= nil;
83 end;
84 end;
85
86 function ResolveIP(AddrInfo: PAddrInfo): ansistring;
87 var
88 r: integer;
89 NodeBuffer: array[0..255] of char;
90 begin
91 NodeBuffer[0]:= #0;
92 r:= getnameinfo(AddrInfo^.ai_addr, AddrInfo^.ai_addrlen, @NodeBuffer, SizeOf(NodeBuffer), nil, 0, 0);
93 if r = 0 then ResolveIP:= PChar(@NodeBuffer)
94 else ResolveIP:= IPToStr(AddrInfo^.ai_addr);
95 end;
96
97 function ResolveIP(SockAddr: PSockAddr): ansistring;
98 var
99 AddrInfo: TAddrInfo;
100 begin
101 AddrInfo.ai_addr:= SockAddr;
102
103 if SockAddr^.sa_family = AF_INET then
104 AddrInfo.ai_addrlen:= SizeOf(TSockAddr)
105 else if SockAddr^.sa_family = AF_INET6 then
106 AddrInfo.ai_addrlen:= SizeOf(TSockAddr6)
107 else
108 AddrInfo.ai_addrlen:= 0;
109
110 ResolveIP:= ResolveIP(PAddrInfo(@AddrInfo));
111 end;
112
113 function IPToStr(SockAddr: PSockAddr): ansistring;
114 begin
115 if SockAddr^.sa_family = AF_INET then
116 IPToStr:= NetAddrToStr(SockAddr^.sin_addr)
117 else if SockAddr^.sa_family = AF_INET6 then
118 IPToStr:= NetAddrToStr6(PSockAddr6(SockAddr)^.sin6_addr)
119 else
120 IPToStr:= 'unknown';
121 end;
122
123
124 end.