X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/4782a5c5afee47721cc617daa40dd29828342c2b..31d4361fb52761b6486f55af10268a51ee536a6f:/dnswin.pas diff --git a/dnswin.pas b/dnswin.pas old mode 100755 new mode 100644 index 7d986d1..567ea68 --- a/dnswin.pas +++ b/dnswin.pas @@ -1,13 +1,16 @@ unit dnswin; interface -uses binipstuff,classes,lcore; + +uses binipstuff,classes,lcore,pgtypes; + +{$include lcoreconfig.inc} //on failure a null string or zeroed out binip will be retuned and error will be //set to a windows error code (error will be left untouched under non error //conditions). -function winforwardlookup(name : string;ipv6preffered : boolean;var error:integer) : tbinip; -function winreverselookup(ip:tbinip;var error:integer):string; +function winforwardlookuplist(name : thostname;familyhint:integer;var error : integer) : tbiniplist; +function winreverselookup(ip:tbinip;var error:integer):thostname; type @@ -17,19 +20,17 @@ type //release should only be called from the main thread tdnswinasync=class(tthread) private - ipv6preffered : boolean; freverse : boolean; - error : integer; freewhendone : boolean; hadevent : boolean; protected procedure execute; override; public onrequestdone:tsocketevent; - name : string; - ip : tbinip; + name : thostname; + iplist : tbiniplist; - procedure forwardlookup(name:string;ipv6preffered:boolean); + procedure forwardlookup(name:thostname); procedure reverselookup(ip:tbinip); destructor destroy; override; procedure release; @@ -40,7 +41,8 @@ type implementation uses - lsocket,pgtypes,sysutils,winsock,windows,messages; + { zipplet: moved pgtypes to interface because it's needed for the string definitions } + lsocket,sysutils,winsock,windows,messages; type //taddrinfo = record; //forward declaration @@ -51,55 +53,76 @@ type ai_socktype : longint; ai_protocol : longint; ai_addrlen : taddrint; - ai_canonname : pchar; + ai_canonname : pansichar; ai_addr : pinetsockaddrv; ai_next : paddrinfo; end; ppaddrinfo = ^paddrinfo; - tgetaddrinfo = function(nodename : pchar; servname : pchar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall; + tgetaddrinfo = function(nodename : pansichar; servname : pansichar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall; tfreeaddrinfo = procedure(ai : paddrinfo); stdcall; - tgetnameinfo = function(sa:Pinetsockaddrv;salen : longint; host:pchar;hostlen : longint;serv:pchar;servlen:longint;flags:longint) : longint;stdcall; + tgetnameinfo = function(sa:Pinetsockaddrv;salen : longint; host:pansichar;hostlen : longint;serv:pansichar;servlen:longint;flags:longint) : longint;stdcall; var getaddrinfo : tgetaddrinfo; freeaddrinfo : tfreeaddrinfo; getnameinfo : tgetnameinfo; procedure v4onlyfreeaddrinfo(ai : paddrinfo); stdcall; +var + next:paddrinfo; begin - freemem(ai.ai_addr); - freemem(ai); + while assigned(ai) do begin + freemem(ai.ai_addr); + next := ai.ai_next; + freemem(ai); + ai := next; + end; end; type plongint = ^longint; pplongint = ^plongint; -function v4onlygetaddrinfo(nodename : pchar; servname : pchar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall; +function v4onlygetaddrinfo(nodename : pansichar; servname : pansichar; hints : paddrinfo;res : ppaddrinfo) : longint; stdcall; var - output : paddrinfo; + output,prev,first : paddrinfo; hostent : phostent; + addrlist:^pointer; begin - if hints.ai_family = af_inet then begin + output := nil; + if hints.ai_family <> af_inet6 then begin result := 0; - getmem(output,sizeof(taddrinfo)); - getmem(output.ai_addr,sizeof(tinetsockaddr)); - output.ai_addr.InAddr.family := af_inet; - if servname <> nil then output.ai_addr.InAddr.port := htons(strtoint(servname)) else output.ai_addr.InAddr.port := 0; + + hostent := gethostbyname(nodename); if hostent = nil then begin result := wsagetlasterror; v4onlyfreeaddrinfo(output); exit; end; - output.ai_addr.InAddr.addr := pplongint(hostent.h_addr_list)^^; - output.ai_flags := 0; - output.ai_family := af_inet; - output.ai_socktype := 0; - output.ai_protocol := 0; - output.ai_addrlen := sizeof(tinetsockaddr); - output.ai_canonname := nil; - output.ai_next := nil; - - res^ := output; + addrlist := pointer(hostent.h_addr_list); + + //ipint := pplongint(hostent.h_addr_list)^^; + prev := nil; + first := nil; + repeat + if not assigned(addrlist^) then break; + + getmem(output,sizeof(taddrinfo)); + if assigned(prev) then prev.ai_next := output; + getmem(output.ai_addr,sizeof(tinetsockaddr)); + if servname <> nil then output.ai_addr.InAddr.port := htons(strtoint(servname)) else output.ai_addr.InAddr.port := 0; + output.ai_addr.InAddr.addr := longint(addrlist^^); + inc(integer(addrlist),4); + output.ai_flags := 0; + output.ai_family := af_inet; + output.ai_socktype := 0; + output.ai_protocol := 0; + output.ai_addrlen := sizeof(tinetsockaddr); + output.ai_canonname := nil; + output.ai_next := nil; + prev := output; + if not assigned(first) then first := output; + until false; + res^ := first; end else begin result := WSANO_RECOVERY; end; @@ -110,7 +133,7 @@ begin if a<b then result := a else result := b; end; -function v4onlygetnameinfo(sa:Pinetsockaddrv;salen : longint; host:pchar;hostlen : longint;serv:pchar;servlen:longint;flags:longint) : longint;stdcall; +function v4onlygetnameinfo(sa:Pinetsockaddrv;salen : longint; host:pansichar;hostlen : longint;serv:pansichar;servlen:longint;flags:longint) : longint;stdcall; var hostent : phostent; bytestocopy : integer; @@ -136,13 +159,13 @@ procedure populateprocvars; var libraryhandle : hmodule; i : integer; - dllname : string; + dllname : ansistring; begin if assigned(getaddrinfo) then exit; //procvars already populated for i := 0 to 1 do begin if i=0 then dllname := 'Ws2_32.dll' else dllname := 'Wship6.dll'; - libraryhandle := LoadLibrary(pchar(dllname)); + libraryhandle := LoadLibraryA(pansichar(dllname)); getaddrinfo := getprocaddress(libraryhandle,'getaddrinfo'); freeaddrinfo := getprocaddress(libraryhandle,'freeaddrinfo'); getnameinfo := getprocaddress(libraryhandle,'getnameinfo'); @@ -159,70 +182,62 @@ begin end; -function winforwardlookup(name : string;ipv6preffered : boolean;var error : integer) : tbinip; +function winforwardlookuplist(name : thostname;familyhint:integer;var error : integer) : tbiniplist; var hints: taddrinfo; - res : paddrinfo; - pass : boolean; - ipv6 : boolean; + res0,res : paddrinfo; getaddrinforesult : integer; + biniptemp:tbinip; begin populateprocvars; - for pass := false to true do begin - ipv6 := ipv6preffered xor pass; - hints.ai_flags := 0; - if ipv6 then begin - hints.ai_family := AF_INET6; - end else begin - hints.ai_family := AF_INET; - end; - hints.ai_socktype := 0; - hints.ai_protocol := 0; - hints.ai_addrlen := 0; - hints.ai_canonname := nil; - hints.ai_addr := nil; - hints.ai_next := nil; - getaddrinforesult := getaddrinfo(pchar(name),'1',@hints,@res); - if getaddrinforesult = 0 then begin + hints.ai_flags := 0; + hints.ai_family := familyhint; + hints.ai_socktype := 0; + hints.ai_protocol := 0; + hints.ai_addrlen := 0; + hints.ai_canonname := nil; + hints.ai_addr := nil; + hints.ai_next := nil; + getaddrinforesult := getaddrinfo(pansichar(name),'1',@hints,@res); + res0 := res; + result := biniplist_new; + if getaddrinforesult = 0 then begin + + while assigned(res) do begin if res.ai_family = af_inet then begin - result.family := af_inet; - result.ip := res.ai_addr.InAddr.addr; - end else {$ifdef ipv6}if res.ai_family = af_inet6 then begin - result.family := af_inet6; - result.ip6 := res.ai_addr.InAddr6.sin6_addr; - end;{$endif}; - - freeaddrinfo(res); - exit; + biniptemp.family := af_inet; + biniptemp.ip := res.ai_addr.InAddr.addr; + biniplist_add(result,biniptemp); + {$ifdef ipv6} + end else if res.ai_family = af_inet6 then begin + biniptemp.family := af_inet6; + biniptemp.ip6 := res.ai_addr.InAddr6.sin6_addr; + biniplist_add(result,biniptemp); + {$endif} + end; + res := res.ai_next; end; + freeaddrinfo(res0); + exit; end; + if getaddrinforesult <> 0 then begin fillchar(result,0,sizeof(result)); error := getaddrinforesult; end; end; -function winreverselookup(ip:tbinip;var error : integer):string; +function winreverselookup(ip:tbinip;var error : integer):thostname; var sa : tinetsockaddrv; getnameinforesult : integer; begin - if ip.family = AF_INET then begin - sa.InAddr.family := AF_INET; - sa.InAddr.port := 1; - sa.InAddr.addr := ip.ip; - end else {$ifdef ipv6}if ip.family = AF_INET6 then begin - sa.InAddr6.sin6_family := AF_INET6; - sa.InAddr6.sin6_port := 1; - sa.InAddr6.sin6_addr := ip.ip6; - end else{$endif} begin - raise exception.create('unrecognised address family'); - end; + makeinaddrv(ip,'1',sa); populateprocvars; setlength(result,1025); - getnameinforesult := getnameinfo(@sa,sizeof(tinetsockaddrv),pchar(result),length(result),nil,0,0); + getnameinforesult := getnameinfo(@sa,sizeof(tinetsockaddrv),pansichar(result),length(result),nil,0,0); if getnameinforesult <> 0 then begin error := getnameinforesult; result := ''; @@ -249,6 +264,7 @@ begin if assigned (dwas.onrequestdone) then dwas.onrequestdone(dwas,awparam); dwas.hadevent := true; if dwas.freewhendone then dwas.free; + result := 0; {added returning 0 when handling --beware} end else begin //not passing unknown messages on to defwindowproc will cause window //creation to fail! --plugwash @@ -256,35 +272,36 @@ begin end; end; -procedure tdnswinasync.forwardlookup(name:string;ipv6preffered:boolean); +procedure tdnswinasync.forwardlookup(name:thostname); begin self.name := name; - self.ipv6preffered := ipv6preffered; freverse := false; resume; end; procedure tdnswinasync.reverselookup(ip:tbinip); begin - self.ip := ip; + iplist := biniplist_new; + biniplist_add(iplist,ip); freverse := true; resume; end; + procedure tdnswinasync.execute; var error : integer; + begin error := 0; if reverse then begin - name := winreverselookup(ip,error); + name := winreverselookup(biniplist_get(iplist,0),error); end else begin - ip := winforwardlookup(name,ipv6preffered,error); + iplist := winforwardlookuplist(name,0,error); end; - postmessage(hwnddnswin,wm_user,error,taddrint(self)); end; -destructor tdnswinasync.destroy; +destructor tdnswinasync.destroy; begin WaitFor; inherited destroy;