unit dnswin;\r
\r
interface\r
-uses binipstuff,classes,lcore;\r
+\r
+uses binipstuff,classes,lcore,pgtypes;\r
+\r
+{$include lcoreconfig.inc}\r
\r
//on failure a null string or zeroed out binip will be retuned and error will be\r
//set to a windows error code (error will be left untouched under non error\r
//conditions).\r
-function winforwardlookup(name : string;ipv6preffered : boolean;var error:integer) : tbinip;\r
-function winreverselookup(ip:tbinip;var error:integer):string;\r
+function winforwardlookuplist(name : thostname;familyhint:integer;var error : integer) : tbiniplist;\r
+function winreverselookup(ip:tbinip;var error:integer):thostname;\r
\r
\r
type\r
//release should only be called from the main thread\r
tdnswinasync=class(tthread)\r
private\r
- ipv6preffered : boolean;\r
freverse : boolean;\r
error : integer;\r
freewhendone : boolean;\r
procedure execute; override;\r
public\r
onrequestdone:tsocketevent;\r
- name : string;\r
- ip : tbinip;\r
+ name : thostname;\r
+ iplist : tbiniplist;\r
\r
- procedure forwardlookup(name:string;ipv6preffered:boolean);\r
+ procedure forwardlookup(name:thostname);\r
procedure reverselookup(ip:tbinip);\r
destructor destroy; override;\r
procedure release;\r
\r
implementation\r
uses\r
- lsocket,pgtypes,sysutils,winsock,windows,messages;\r
+ { zipplet: moved pgtypes to interface because it's needed for the string definitions }\r
+ lsocket,sysutils,winsock,windows,messages;\r
\r
type\r
//taddrinfo = record; //forward declaration\r
ai_socktype : longint;\r
ai_protocol : longint;\r
ai_addrlen : taddrint;\r
- ai_canonname : pchar;\r
+ ai_canonname : pansichar;\r
ai_addr : pinetsockaddrv;\r
ai_next : paddrinfo;\r
end;\r
ppaddrinfo = ^paddrinfo;\r
- tgetaddrinfo = function(nodename : pchar; servname : pchar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall;\r
+ tgetaddrinfo = function(nodename : pansichar; servname : pansichar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall;\r
tfreeaddrinfo = procedure(ai : paddrinfo); stdcall;\r
- tgetnameinfo = function(sa:Pinetsockaddrv;salen : longint; host:pchar;hostlen : longint;serv:pchar;servlen:longint;flags:longint) : longint;stdcall;\r
+ tgetnameinfo = function(sa:Pinetsockaddrv;salen : longint; host:pansichar;hostlen : longint;serv:pansichar;servlen:longint;flags:longint) : longint;stdcall;\r
var\r
getaddrinfo : tgetaddrinfo;\r
freeaddrinfo : tfreeaddrinfo;\r
getnameinfo : tgetnameinfo;\r
procedure v4onlyfreeaddrinfo(ai : paddrinfo); stdcall;\r
+var\r
+ next:paddrinfo;\r
begin\r
- freemem(ai.ai_addr);\r
- freemem(ai);\r
+ while assigned(ai) do begin\r
+ freemem(ai.ai_addr);\r
+ next := ai.ai_next;\r
+ freemem(ai);\r
+ ai := next;\r
+ end;\r
end;\r
\r
type\r
plongint = ^longint;\r
pplongint = ^plongint;\r
\r
-function v4onlygetaddrinfo(nodename : pchar; servname : pchar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall;\r
+function v4onlygetaddrinfo(nodename : pansichar; servname : pansichar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall;\r
var\r
- output : paddrinfo;\r
+ output,prev,first : paddrinfo;\r
hostent : phostent;\r
+ addrlist:^pointer;\r
begin\r
- if hints.ai_family = af_inet then begin\r
+ if hints.ai_family <> af_inet6 then begin\r
result := 0;\r
- getmem(output,sizeof(taddrinfo));\r
- getmem(output.ai_addr,sizeof(tinetsockaddr));\r
- output.ai_addr.InAddr.family := af_inet;\r
- if servname <> nil then output.ai_addr.InAddr.port := htons(strtoint(servname)) else output.ai_addr.InAddr.port := 0;\r
+\r
+\r
hostent := gethostbyname(nodename);\r
if hostent = nil then begin\r
result := wsagetlasterror;\r
v4onlyfreeaddrinfo(output);\r
exit;\r
end;\r
- output.ai_addr.InAddr.addr := pplongint(hostent.h_addr_list)^^;\r
- output.ai_flags := 0;\r
- output.ai_family := af_inet;\r
- output.ai_socktype := 0;\r
- output.ai_protocol := 0;\r
- output.ai_addrlen := sizeof(tinetsockaddr);\r
- output.ai_canonname := nil;\r
- output.ai_next := nil;\r
-\r
- res^ := output;\r
+ addrlist := pointer(hostent.h_addr_list);\r
+\r
+ //ipint := pplongint(hostent.h_addr_list)^^;\r
+ prev := nil;\r
+ first := nil;\r
+ repeat\r
+ if not assigned(addrlist^) then break;\r
+\r
+ getmem(output,sizeof(taddrinfo));\r
+ if assigned(prev) then prev.ai_next := output;\r
+ getmem(output.ai_addr,sizeof(tinetsockaddr));\r
+ if servname <> nil then output.ai_addr.InAddr.port := htons(strtoint(servname)) else output.ai_addr.InAddr.port := 0;\r
+ output.ai_addr.InAddr.addr := longint(addrlist^^);\r
+ inc(integer(addrlist),4);\r
+ output.ai_flags := 0;\r
+ output.ai_family := af_inet;\r
+ output.ai_socktype := 0;\r
+ output.ai_protocol := 0;\r
+ output.ai_addrlen := sizeof(tinetsockaddr);\r
+ output.ai_canonname := nil;\r
+ output.ai_next := nil;\r
+ prev := output;\r
+ if not assigned(first) then first := output;\r
+ until false;\r
+ res^ := first;\r
end else begin\r
result := WSANO_RECOVERY;\r
end;\r
if a<b then result := a else result := b;\r
end;\r
\r
-function v4onlygetnameinfo(sa:Pinetsockaddrv;salen : longint; host:pchar;hostlen : longint;serv:pchar;servlen:longint;flags:longint) : longint;stdcall;\r
+function v4onlygetnameinfo(sa:Pinetsockaddrv;salen : longint; host:pansichar;hostlen : longint;serv:pansichar;servlen:longint;flags:longint) : longint;stdcall;\r
var\r
hostent : phostent;\r
bytestocopy : integer;\r
var\r
libraryhandle : hmodule;\r
i : integer;\r
- dllname : string;\r
+ dllname : ansistring;\r
\r
begin\r
if assigned(getaddrinfo) then exit; //procvars already populated\r
for i := 0 to 1 do begin\r
if i=0 then dllname := 'Ws2_32.dll' else dllname := 'Wship6.dll';\r
- libraryhandle := LoadLibrary(pchar(dllname));\r
+ libraryhandle := LoadLibraryA(pansichar(dllname));\r
getaddrinfo := getprocaddress(libraryhandle,'getaddrinfo');\r
freeaddrinfo := getprocaddress(libraryhandle,'freeaddrinfo');\r
getnameinfo := getprocaddress(libraryhandle,'getnameinfo');\r
end;\r
\r
\r
-function winforwardlookup(name : string;ipv6preffered : boolean;var error : integer) : tbinip;\r
+function winforwardlookuplist(name : thostname;familyhint:integer;var error : integer) : tbiniplist;\r
var\r
hints: taddrinfo;\r
- res : paddrinfo;\r
- pass : boolean;\r
- ipv6 : boolean;\r
+ res0,res : paddrinfo;\r
getaddrinforesult : integer;\r
+ biniptemp:tbinip;\r
begin\r
populateprocvars;\r
\r
- for pass := false to true do begin\r
- ipv6 := ipv6preffered xor pass;\r
- hints.ai_flags := 0;\r
- if ipv6 then begin\r
- hints.ai_family := AF_INET6;\r
- end else begin\r
- hints.ai_family := AF_INET;\r
- end;\r
- hints.ai_socktype := 0;\r
- hints.ai_protocol := 0;\r
- hints.ai_addrlen := 0;\r
- hints.ai_canonname := nil;\r
- hints.ai_addr := nil;\r
- hints.ai_next := nil;\r
- getaddrinforesult := getaddrinfo(pchar(name),'1',@hints,@res);\r
- if getaddrinforesult = 0 then begin\r
+ hints.ai_flags := 0;\r
+ hints.ai_family := familyhint;\r
+ hints.ai_socktype := 0;\r
+ hints.ai_protocol := 0;\r
+ hints.ai_addrlen := 0;\r
+ hints.ai_canonname := nil;\r
+ hints.ai_addr := nil;\r
+ hints.ai_next := nil;\r
+ getaddrinforesult := getaddrinfo(pansichar(name),'1',@hints,@res);\r
+ res0 := res;\r
+ result := biniplist_new;\r
+ if getaddrinforesult = 0 then begin\r
+\r
+ while assigned(res) do begin\r
if res.ai_family = af_inet then begin\r
- result.family := af_inet;\r
- result.ip := res.ai_addr.InAddr.addr;\r
- end else {$ifdef ipv6}if res.ai_family = af_inet6 then begin\r
- result.family := af_inet6;\r
- result.ip6 := res.ai_addr.InAddr6.sin6_addr;\r
- end;{$endif};\r
-\r
- freeaddrinfo(res);\r
- exit;\r
+ biniptemp.family := af_inet;\r
+ biniptemp.ip := res.ai_addr.InAddr.addr;\r
+ biniplist_add(result,biniptemp);\r
+ {$ifdef ipv6}\r
+ end else if res.ai_family = af_inet6 then begin\r
+ biniptemp.family := af_inet6;\r
+ biniptemp.ip6 := res.ai_addr.InAddr6.sin6_addr;\r
+ biniplist_add(result,biniptemp);\r
+ {$endif}\r
+ end;\r
+ res := res.ai_next;\r
end;\r
+ freeaddrinfo(res0);\r
+ exit;\r
end;\r
+\r
if getaddrinforesult <> 0 then begin\r
fillchar(result,0,sizeof(result));\r
error := getaddrinforesult;\r
end;\r
end;\r
\r
-function winreverselookup(ip:tbinip;var error : integer):string;\r
+function winreverselookup(ip:tbinip;var error : integer):thostname;\r
var\r
sa : tinetsockaddrv;\r
getnameinforesult : integer;\r
begin\r
\r
- if ip.family = AF_INET then begin\r
- sa.InAddr.family := AF_INET;\r
- sa.InAddr.port := 1;\r
- sa.InAddr.addr := ip.ip;\r
- end else {$ifdef ipv6}if ip.family = AF_INET6 then begin\r
- sa.InAddr6.sin6_family := AF_INET6;\r
- sa.InAddr6.sin6_port := 1;\r
- sa.InAddr6.sin6_addr := ip.ip6;\r
- end else{$endif} begin\r
- raise exception.create('unrecognised address family');\r
- end;\r
+ makeinaddrv(ip,'1',sa);\r
populateprocvars;\r
setlength(result,1025);\r
- getnameinforesult := getnameinfo(@sa,sizeof(tinetsockaddrv),pchar(result),length(result),nil,0,0);\r
+ getnameinforesult := getnameinfo(@sa,sizeof(tinetsockaddrv),pansichar(result),length(result),nil,0,0);\r
if getnameinforesult <> 0 then begin\r
error := getnameinforesult;\r
result := '';\r
end;\r
end;\r
\r
-procedure tdnswinasync.forwardlookup(name:string;ipv6preffered:boolean);\r
+procedure tdnswinasync.forwardlookup(name:thostname);\r
begin\r
self.name := name;\r
- self.ipv6preffered := ipv6preffered;\r
freverse := false;\r
resume;\r
end;\r
procedure tdnswinasync.reverselookup(ip:tbinip);\r
begin\r
- self.ip := ip;\r
+ iplist := biniplist_new;\r
+ biniplist_add(iplist,ip);\r
freverse := true;\r
resume;\r
end;\r
+\r
procedure tdnswinasync.execute;\r
var\r
error : integer;\r
+\r
begin\r
error := 0;\r
if reverse then begin\r
- name := winreverselookup(ip,error);\r
+ name := winreverselookup(biniplist_get(iplist,0),error);\r
end else begin\r
- ip := winforwardlookup(name,ipv6preffered,error);\r
+ iplist := winforwardlookuplist(name,0,error);\r
\r
end;\r
-\r
postmessage(hwnddnswin,wm_user,error,taddrint(self));\r
end;\r
\r
-destructor tdnswinasync.destroy; \r
+destructor tdnswinasync.destroy;\r
begin\r
WaitFor;\r
inherited destroy;\r