From eaa75975b23ce60360526c08628f2b0651c95167 Mon Sep 17 00:00:00 2001 From: beware Date: Thu, 24 Feb 2011 06:24:10 +0000 Subject: [PATCH 1/1] reorganization of system dns servers code git-svn-id: file:///svnroot/lcore/trunk@97 b1de8a11-f9be-4011-bde0-cc7ace90066a --- dnsasync.pas | 12 ++-- dnscore.pas | 156 ++++++++++++-------------------------------- dnssync.pas | 16 ++--- lcorelocalips.pas | 162 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 212 insertions(+), 134 deletions(-) diff --git a/dnsasync.pas b/dnsasync.pas index 4efc205..b6e8941 100644 --- a/dnsasync.pas +++ b/dnsasync.pas @@ -153,7 +153,7 @@ end; function tdnsasync.sendquery(socketno:integer;const packet:tdnspacket;len:integer):boolean; var - destination : ansistring; + destination : tbinip; inaddr : tinetsockaddrv; trytolisten:integer; begin @@ -185,11 +185,11 @@ begin end; if addr <> '' then begin dnsserverids[socketno] := -1; - destination := addr + destination := ipstrtobinf(addr); end else begin - destination := getcurrentsystemnameserver(dnsserverids[socketno]); + destination := getcurrentsystemnameserverbin(dnsserverids[socketno]); end; - destinations[socketno] := ipstrtobinf(destination); + destinations[socketno] := destination; {$ifdef ipv6}{$ifdef win32} if destinations[socketno].family = AF_INET6 then if (requestaf = useaf_default) then requestaf := useaf_preferv6; @@ -255,8 +255,6 @@ begin exit; end; - if (overridednsserver <> '') and (addr = '') then addr := overridednsserver; - if overrideaf = useaf_default then begin {$ifdef ipv6} {$ifdef win32}if not (usewindns and (addr = '')) then{$endif} @@ -299,7 +297,6 @@ end; procedure tdnsasync.reverselookup; begin - if (overridednsserver <> '') and (addr = '') then addr := overridednsserver; {$ifdef win32} if usewindns and (addr = '') then begin dwas := tdnswinasync.create; @@ -316,7 +313,6 @@ end; procedure tdnsasync.customlookup; begin - if (overridednsserver <> '') and (addr = '') then addr := overridednsserver; setstate_custom(name,querytype,states[0]); numsockused := 1; asyncprocess(0); diff --git a/dnscore.pas b/dnscore.pas index 18e40c9..fa9eee2 100644 --- a/dnscore.pas +++ b/dnscore.pas @@ -188,7 +188,8 @@ procedure populatednsserverlist; procedure cleardnsservercache; var - dnsserverlist : tstringlist; + dnsserverlist : tbiniplist; + dnsserverlag:tlist; // currentdnsserverno : integer; @@ -196,6 +197,7 @@ var //id to the id of that nameserver. id should later be used to report how laggy //the servers response was and if it was timed out. function getcurrentsystemnameserver(var id:integer) :ansistring; +function getcurrentsystemnameserverbin(var id:integer) :tbinip; procedure reportlag(id:integer;lag:integer); //lag should be in microseconds and should be -1 to report a timeout //var @@ -219,9 +221,6 @@ function getquerytype(s:ansistring):integer; implementation uses - {$ifdef win32} - windows, - {$endif} lcorelocalips, sysutils; @@ -605,132 +604,59 @@ recursed: failure: setstate_failure(state); end; -{$ifdef win32} - const - MAX_HOSTNAME_LEN = 132; - MAX_DOMAIN_NAME_LEN = 132; - MAX_SCOPE_ID_LEN = 260 ; - MAX_ADAPTER_NAME_LENGTH = 260; - MAX_ADAPTER_ADDRESS_LENGTH = 8; - MAX_ADAPTER_DESCRIPTION_LENGTH = 132; - ERROR_BUFFER_OVERFLOW = 111; - MIB_IF_TYPE_ETHERNET = 6; - MIB_IF_TYPE_TOKENRING = 9; - MIB_IF_TYPE_FDDI = 15; - MIB_IF_TYPE_PPP = 23; - MIB_IF_TYPE_LOOPBACK = 24; - MIB_IF_TYPE_SLIP = 28; - - - type - tip_addr_string=packed record - Next :pointer; - IpAddress : array[0..15] of ansichar; - ipmask : array[0..15] of ansichar; - context : dword; - end; - pip_addr_string=^tip_addr_string; - tFIXED_INFO=packed record - HostName : array[0..MAX_HOSTNAME_LEN-1] of ansichar; - DomainName : array[0..MAX_DOMAIN_NAME_LEN-1] of ansichar; - currentdnsserver : pip_addr_string; - dnsserverlist : tip_addr_string; - nodetype : longint; - ScopeId : array[0..MAX_SCOPE_ID_LEN + 4] of ansichar; - enablerouting : longbool; - enableproxy : longbool; - enabledns : longbool; - end; - pFIXED_INFO=^tFIXED_INFO; - var - iphlpapi : thandle; - getnetworkparams : function(pFixedInfo : PFIXED_INFO;OutBufLen : plongint) : longint;stdcall; -{$endif} + procedure populatednsserverlist; var - {$ifdef win32} - fixed_info : pfixed_info; - fixed_info_len : longint; - currentdnsserver : pip_addr_string; - {$else} - t:textfile; - s:ansistring; - a:integer; - {$endif} + a:integer; begin - //result := ''; - if assigned(dnsserverlist) then begin - dnsserverlist.clear; + if assigned(dnsserverlag) then begin + dnsserverlag.clear; end else begin - dnsserverlist := tstringlist.Create; + dnsserverlag := tlist.Create; end; - {$ifdef win32} - if iphlpapi=0 then iphlpapi := loadlibrary('iphlpapi.dll'); - if not assigned(getnetworkparams) then @getnetworkparams := getprocaddress(iphlpapi,'GetNetworkParams'); - if not assigned(getnetworkparams) then exit; - fixed_info_len := 0; - if GetNetworkParams(nil,@fixed_info_len)<>ERROR_BUFFER_OVERFLOW then exit; - //fixed_info_len :=sizeof(tfixed_info); - getmem(fixed_info,fixed_info_len); - if GetNetworkParams(fixed_info,@fixed_info_len)<>0 then begin - freemem(fixed_info); - exit; - end; - currentdnsserver := @(fixed_info.dnsserverlist); - while assigned(currentdnsserver) do begin - dnsserverlist.Add(currentdnsserver.IpAddress); - currentdnsserver := currentdnsserver.next; - end; - freemem(fixed_info); - {$else} - filemode := 0; - assignfile(t,'/etc/resolv.conf'); - {$i-}reset(t);{$i+} - if ioresult <> 0 then exit; - - while not eof(t) do begin - readln(t,s); - if not (copy(s,1,10) = 'nameserver') then continue; - s := copy(s,11,500); - while s <> '' do begin - if (s[1] = #32) or (s[1] = #9) then s := copy(s,2,500) else break; - end; - a := pos(' ',s); - if a <> 0 then s := copy(s,1,a-1); - a := pos(#9,s); - if a <> 0 then s := copy(s,1,a-1); - //result := s; - //if result <> '' then break; - dnsserverlist.Add(s); - end; - close(t); - {$endif} + + dnsserverlist := getsystemdnsservers; + for a := biniplist_getcount(dnsserverlist)-1 downto 0 do dnsserverlag.Add(nil); end; procedure cleardnsservercache; begin - if assigned(dnsserverlist) then begin - dnsserverlist.destroy; - dnsserverlist := nil; + if assigned(dnsserverlag) then begin + dnsserverlag.destroy; + dnsserverlag := nil; + dnsserverlist := ''; end; end; -function getcurrentsystemnameserver(var id:integer):ansistring; +function getcurrentsystemnameserverbin(var id:integer):tbinip; var counter : integer; - begin - if not assigned(dnsserverlist) then populatednsserverlist; - if dnsserverlist.count=0 then raise exception.create('no dns servers availible'); - id := 0; - if dnsserverlist.count >1 then begin + {override the name server choice here, instead of overriding it whereever it's called + setting ID to -1 causes it to be ignored in reportlag} + if (overridednsserver <> '') then begin + result := ipstrtobinf(overridednsserver); + if result.family <> 0 then begin + id := -1; + exit; + end; + end; - for counter := 1 to dnsserverlist.count-1 do begin - if taddrint(dnsserverlist.objects[counter]) < taddrint(dnsserverlist.objects[id]) then id := counter; + if not assigned(dnsserverlag) then populatednsserverlist; + if dnsserverlag.count=0 then raise exception.create('no dns servers availible'); + id := 0; + if dnsserverlag.count >1 then begin + for counter := dnsserverlag.count-1 downto 1 do begin + if taddrint(dnsserverlag[counter]) < taddrint(dnsserverlag[id]) then id := counter; end; end; - result := dnsserverlist[id] + result := biniplist_get(dnsserverlist,id); +end; + +function getcurrentsystemnameserver(var id:integer):ansistring; +begin + result := ipbintostr(getcurrentsystemnameserverbin(id)); end; procedure reportlag(id:integer;lag:integer); //lag should be in microseconds and should be -1 to report a timeout @@ -738,12 +664,12 @@ var counter : integer; temp : integer; begin - if (id < 0) or (id >= dnsserverlist.count) then exit; + if (id < 0) or (id >= dnsserverlag.count) then exit; if lag = -1 then lag := timeoutlag; - for counter := 0 to dnsserverlist.count-1 do begin - temp := taddrint(dnsserverlist.objects[counter]) *15; + for counter := 0 to dnsserverlag.count-1 do begin + temp := taddrint(dnsserverlag[counter]) *15; if counter=id then temp := temp + lag; - dnsserverlist.objects[counter] := tobject(temp div 16); + dnsserverlag[counter] := tobject(temp div 16); end; end; diff --git a/dnssync.pas b/dnssync.pas index c603b92..1a506d5 100644 --- a/dnssync.pas +++ b/dnssync.pas @@ -109,7 +109,7 @@ end; function sendquery(socknum:integer;const packet:tdnspacket;len:integer):boolean; var - addr : ansistring; + ip : tbinip; port : ansistring; inaddr : TInetSockAddrV; begin @@ -117,14 +117,14 @@ begin result := false; if len = 0 then exit; {no packet} - if overridednsserver <> '' then addr := overridednsserver else addr := getcurrentsystemnameserver(id); + ip := getcurrentsystemnameserverbin(id); {$ifdef ipv6}{$ifdef win32} if toaddr[socknum].family = AF_INET6 then if (useaf = 0) then useaf := useaf_preferv6; {$endif}{$endif} port := toport; - toaddr[socknum] := ipstrtobinf(addr); + toaddr[socknum] := ip; makeinaddrv(toaddr[socknum],port,inaddr); sendto(fd[socknum],packet,len,0,inaddr,inaddrsize(inaddr)); @@ -137,16 +137,14 @@ var inAddrtemp : TInetSockAddrV; a:integer; biniptemp:tbinip; - addr:ansistring; + begin //init both sockets smultaneously, always, so they get succesive fd's if fd[0] > 0 then exit; - if overridednsserver <> '' then addr := overridednsserver else addr := getcurrentsystemnameserver(id); + biniptemp := getcurrentsystemnameserverbin(id); //must get the DNS server here so we know to init v4 or v6 - ipstrtobin(addr,biniptemp); - if biniptemp.family = AF_INET6 then biniptemp := ipstrtobinf('::') else biniptemp := ipstrtobinf('0.0.0.0'); @@ -255,7 +253,7 @@ begin fillchar(state[socknum].recvpacket,sizeof(state[socknum].recvpacket),0); msectotimeval(lag,(currenttime-sendquerytime[socknum]) and tsmask); - if overridednsserver = '' then reportlag(id,(lag.tv_sec*1000000)+lag.tv_usec); + reportlag(id,(lag.tv_sec*1000000)+lag.tv_usec); SrcLen := SizeOf(Src); state[socknum].recvpacketlen := recvfrom(fd[socknum],state[socknum].recvpacket, SizeOf(state[socknum].recvpacket),0,Srcx,SrcLen); @@ -278,7 +276,7 @@ begin currenttime := getts; - if overridednsserver = '' then reportlag(id,-1); + reportlag(id,-1); if (currenttime >= endtime) and ((not wrapmode) or (currenttime < starttime)) then begin exit; end else begin diff --git a/lcorelocalips.pas b/lcorelocalips.pas index 7e03c1b..d20a04f 100644 --- a/lcorelocalips.pas +++ b/lcorelocalips.pas @@ -4,7 +4,10 @@ ----------------------------------------------------------------------------- } { -unit to get IP addresses assigned to local interfaces. +unit to get various local system config + + +- get IP addresses assigned to local interfaces. both IPv4 and IPv6, or one address family in isolation. works on both windows and linux. @@ -17,6 +20,12 @@ notes: an app that doesn't want link local IPs has to filter them out. windows XP returns only one, global scope, v6 IP, due to shortcomings. + + +- get system DNS servers + +- get system hostname + } unit lcorelocalips; @@ -33,6 +42,9 @@ function getv4localips:tbiniplist; function getv6localips:tbiniplist; {$endif} +function getsystemdnsservers:tbiniplist; +function getsystemhostname:ansistring; + implementation {$ifdef linux} @@ -130,7 +142,7 @@ end; {$else} uses - sysutils,winsock,dnssync; + sysutils,windows,winsock,dnssync; {the following code's purpose is to determine what IP windows would come from, to reach an IP it can be abused to find if there's any global v6 IPs on a local interface} @@ -222,4 +234,150 @@ end; + + +{$ifdef win32} + const + MAX_HOSTNAME_LEN = 132; + MAX_DOMAIN_NAME_LEN = 132; + MAX_SCOPE_ID_LEN = 260 ; + MAX_ADAPTER_NAME_LENGTH = 260; + MAX_ADAPTER_ADDRESS_LENGTH = 8; + MAX_ADAPTER_DESCRIPTION_LENGTH = 132; + ERROR_BUFFER_OVERFLOW = 111; + MIB_IF_TYPE_ETHERNET = 6; + MIB_IF_TYPE_TOKENRING = 9; + MIB_IF_TYPE_FDDI = 15; + MIB_IF_TYPE_PPP = 23; + MIB_IF_TYPE_LOOPBACK = 24; + MIB_IF_TYPE_SLIP = 28; + + + type + tip_addr_string=packed record + Next :pointer; + IpAddress : array[0..15] of ansichar; + ipmask : array[0..15] of ansichar; + context : dword; + end; + pip_addr_string=^tip_addr_string; + tFIXED_INFO=packed record + HostName : array[0..MAX_HOSTNAME_LEN-1] of ansichar; + DomainName : array[0..MAX_DOMAIN_NAME_LEN-1] of ansichar; + currentdnsserver : pip_addr_string; + dnsserverlist : tip_addr_string; + nodetype : longint; + ScopeId : array[0..MAX_SCOPE_ID_LEN + 4] of ansichar; + enablerouting : longbool; + enableproxy : longbool; + enabledns : longbool; + end; + pFIXED_INFO=^tFIXED_INFO; + + var + iphlpapi : thandle; + getnetworkparams : function(pFixedInfo : PFIXED_INFO;OutBufLen : plongint) : longint;stdcall; + +function callGetNetworkParams:pFIXED_INFO; +var + fixed_info : pfixed_info; + fixed_info_len : longint; +begin + result := nil; + if iphlpapi=0 then iphlpapi := loadlibrary('iphlpapi.dll'); + if not assigned(getnetworkparams) then @getnetworkparams := getprocaddress(iphlpapi,'GetNetworkParams'); + if not assigned(getnetworkparams) then exit; + fixed_info_len := 0; + if GetNetworkParams(nil,@fixed_info_len)<>ERROR_BUFFER_OVERFLOW then exit; + //fixed_info_len :=sizeof(tfixed_info); + getmem(fixed_info,fixed_info_len); + if GetNetworkParams(fixed_info,@fixed_info_len)<>0 then begin + freemem(fixed_info); + exit; + end; + result := fixed_info; +end; + +{$endif} + +function getsystemdnsservers:tbiniplist; +var + {$ifdef win32} + fixed_info : pfixed_info; + currentdnsserver : pip_addr_string; + {$else} + t:textfile; + s:ansistring; + a:integer; + {$endif} + ip:tbinip; +begin + //result := ''; + + result := biniplist_new; + + {$ifdef win32} + fixed_info := callgetnetworkparams; + if fixed_info = nil then exit; + + currentdnsserver := @(fixed_info.dnsserverlist); + while assigned(currentdnsserver) do begin + ip := ipstrtobinf(currentdnsserver.IpAddress); + if (ip.family <> 0) then biniplist_add(result,ip); + currentdnsserver := currentdnsserver.next; + end; + freemem(fixed_info); + {$else} + filemode := 0; + assignfile(t,'/etc/resolv.conf'); + {$i-}reset(t);{$i+} + if ioresult <> 0 then exit; + + while not eof(t) do begin + readln(t,s); + if not (copy(s,1,10) = 'nameserver') then continue; + s := copy(s,11,500); + while s <> '' do begin + if (s[1] = #32) or (s[1] = #9) then s := copy(s,2,500) else break; + end; + a := pos(' ',s); + if a <> 0 then s := copy(s,1,a-1); + a := pos(#9,s); + if a <> 0 then s := copy(s,1,a-1); + + ip := ipstrtobinf(s); + if (ip.family <> 0) then biniplist_add(result,ip); + end; + closefile(t); + {$endif} +end; + + +function getsystemhostname:ansistring; +var + {$ifdef win32} + fixed_info : pfixed_info; + {$else} + t:textfile; + {$endif} +begin + result := ''; + {$ifdef win32} + fixed_info := callgetnetworkparams; + if fixed_info = nil then exit; + + result := fixed_info.hostname; + if fixed_info.domainname <> '' then result := result + '.'+fixed_info.domainname; + + freemem(fixed_info); + {$else} + filemode := 0; + assignfile(t,'/etc/hostname'); + {$i-}reset(t);{$i+} + if ioresult <> 0 then exit; + readln(t,result); + closefile(t); + {$endif} +end; + end. -- 2.30.2