rm some cruft that got imported accidently
[lcore.git] / httpserver_20080306 / dnscore.pas
diff --git a/httpserver_20080306/dnscore.pas b/httpserver_20080306/dnscore.pas
deleted file mode 100755 (executable)
index bb4fab4..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-{ Copyright (C) 2005 Bas Steendijk and Peter Green\r
-  For conditions of distribution and use, see copyright notice in zlib_license.txt\r
-  which is included in the package\r
-  ----------------------------------------------------------------------------- }\r
-\r
-{\r
-\r
-  code wanting to use this dns system should act as follows (note: app\r
-  developers will probablly want to use dnsasync or dnssync or write a similar\r
-  wrapper unit of thier own).\r
-\r
-  for normal lookups call setstate_forward or setstate_reverse to set up the\r
-  state, for more obscure lookups use setstate_request_init and fill in other\r
-  relavent state manually.\r
-\r
-  call state_process which will do processing on the information in the state\r
-  and return an action\r
-  action_ignore means that dnscore wants the code that calls it to go\r
-  back to waiting for packets\r
-  action_sendpacket means that dnscore wants the code that calls it to send\r
-  the packet in sendpacket/sendpacketlen and then start (or go back to) listening\r
-  for\r
-  action_done means the request has completed (either suceeded or failed)\r
-\r
-  callers should resend the last packet they tried to send if they have not\r
-  been asked to send a new packet for more than some timeout value they choose.\r
-\r
-  when a packet is received the application should put the packet in\r
-  recvbuf/recvbuflen , set state.parsepacket and call state_process again\r
-\r
-  once the app gets action_done it can determine sucess or failure in the\r
-  following ways.\r
-\r
-  on failure state.resultstr will be an empty string and state.resultbin will\r
-  be zeroed out (easilly detected by the fact that it will have a family of 0)\r
-\r
-  on success for a A or AAAA lookup state.resultstr will be an empty string\r
-  and state.resultbin will contain the result (note: AAAA lookups require IPV6\r
-  enabled).\r
-\r
-  if an A lookup fails and the code is built with ipv6 enabled then the code\r
-  will return any AAAA records with the same name. The reverse does not apply\r
-  so if an application preffers IPV6 but wants IPV4 results as well it must\r
-  check them seperately.\r
-\r
-  on success for any other type of lookup state.resultstr will be an empty\r
-\r
-  note the state contains ansistrings, setstate_init with a null name parameter\r
-  can be used to clean theese up if required.\r
-\r
-  callers may use setstate_failure to mark the state as failed themseleves\r
-  before passing it on to other code, for example this may be done in the event\r
-  of a timeout.\r
-}\r
-unit dnscore;\r
-\r
-\r
-\r
-{$ifdef fpc}{$mode delphi}{$endif}\r
-\r
-\r
-\r
-\r
-\r
-interface\r
-\r
-uses binipstuff,classes,pgtypes;\r
-\r
-var usewindns : boolean = {$ifdef win32}true{$else}false{$endif};\r
-//hint to users of this unit that they should use windows dns instead.\r
-//May be disabled by applications if desired. (e.g. if setting a custom\r
-//dnsserverlist).\r
-\r
-//note: this unit will not be able to self populate it's dns server list on\r
-//older versions of windows.\r
-\r
-const\r
-  maxnamelength=127;\r
-  maxnamefieldlen=63;\r
-  //note: when using action_ignore the dnscore code *must* preserve the contents of state.sendpacket to allow for retries\r
-  //note: action_ignore must not be used in response to the original request but there is no valid reason for doing this anyway\r
-  action_ignore=0;\r
-  action_done=1;\r
-  action_sendquery=2;\r
-  querytype_a=1;\r
-  querytype_cname=5;\r
-  querytype_aaaa=28;\r
-  querytype_ptr=12;\r
-  querytype_ns=2;\r
-  querytype_soa=6;\r
-  querytype_mx=15;\r
-\r
-  maxrecursion=10;\r
-  maxrrofakind=20;\r
-\r
-  retryafter=300000; //microseconds must be less than one second;\r
-  timeoutlag=1000000000; // penalty value to be treated as lag in the event of a timeout (microseconds)\r
-type\r
-  dvar=array[0..0] of byte;\r
-  pdvar=^dvar;\r
-  tdnspacket=packed record\r
-    id:word;\r
-    flags:word;\r
-    rrcount:array[0..3] of word;\r
-    payload:array[0..511-12] of byte;\r
-  end;\r
-\r
-\r
-\r
-  tdnsstate=record\r
-    id:word;\r
-    recursioncount:integer;\r
-    queryname:string;\r
-    requesttype:word;\r
-    parsepacket:boolean;\r
-    resultstr:string;\r
-    resultbin:tbinip;\r
-    resultaction:integer;\r
-    numrr1:array[0..3] of integer;\r
-    numrr2:integer;\r
-    rrdata:string;\r
-    sendpacketlen:integer;\r
-    sendpacket:tdnspacket;\r
-    recvpacketlen:integer;\r
-    recvpacket:tdnspacket;\r
-    forwardfamily:integer;\r
-  end;\r
-\r
-  trr=packed record\r
-    requesttypehi:byte;\r
-    requesttype:byte;\r
-    clas:word;\r
-    ttl:integer;\r
-    datalen:word;\r
-    data:array[0..511] of byte;\r
-  end;\r
-\r
-  trrpointer=packed record\r
-    p:pointer;\r
-    ofs:integer;\r
-    len:integer;\r
-    namelen:integer;\r
-  end;\r
-\r
-//commenting out functions from interface that do not have documented semantics\r
-//and probablly should not be called from outside this unit, reenable them\r
-//if you must but please document them at the same time --plugwash\r
-\r
-//function buildrequest(const name:string;var packet:tdnspacket;requesttype:word):integer;\r
-//function makereversename(const binip:tbinip):string;\r
-\r
-procedure setstate_request_init(const name:string;var state:tdnsstate);\r
-\r
-//set up state for a foward lookup. A family value of AF_INET6 will give only\r
-//ipv6 results. Any other value will give ipv4 results in preference and ipv6\r
-//results if ipv4 results are not available;\r
-procedure setstate_forward(const name:string;var state:tdnsstate;family:integer);\r
-\r
-procedure setstate_reverse(const binip:tbinip;var state:tdnsstate);\r
-procedure setstate_failure(var state:tdnsstate);\r
-//procedure setstate_return(const rrp:trrpointer;len:integer;var state:tdnsstate);\r
-\r
-\r
-procedure state_process(var state:tdnsstate);\r
-\r
-//function decodename(const packet:tdnspacket;len,start,recursion:integer;var numread:integer):string;\r
-\r
-//presumablly this is exported to allow more secure random functions\r
-//to be substituted?\r
-var randomfunction:function:integer;\r
-\r
-\r
-procedure populatednsserverlist;\r
-procedure cleardnsservercache;\r
-\r
-var\r
-  dnsserverlist : tstringlist;\r
-//  currentdnsserverno : integer;\r
-\r
-function getcurrentsystemnameserver(var id:integer) :string;\r
-\r
-//var\r
-//  unixnameservercache:string;\r
-{ $endif}\r
-\r
-\r
-procedure reportlag(id:integer;lag:integer); //lag should be in microseconds and should be -1 to report a timeout\r
-var\r
-  failurereason:string;\r
-\r
-implementation\r
-\r
-uses\r
-  {$ifdef win32}\r
-    windows,\r
-  {$endif}\r
-\r
-  sysutils;\r
-\r
-function buildrequest(const name:string;var packet:tdnspacket;requesttype:word):integer;\r
-var\r
-  a,b:integer;\r
-  s:string;\r
-  arr:array[0..sizeof(packet)-1] of byte absolute packet;\r
-begin\r
- { writeln('buildrequest: name: ',name);}\r
-  result := 0;\r
-  fillchar(packet,sizeof(packet),0);\r
-  if assigned(randomfunction) then packet.id := (randomfunction and $ffff) else packet.id := random(65536);\r
-  packet.flags := htons($0100);\r
-  packet.rrcount[0] := htons($0001);\r
-\r
-\r
-  s := copy(name,1,maxnamelength);\r
-  if s = '' then exit;\r
-  if s[length(s)] <> '.' then s := s + '.';\r
-  b := 0;\r
-  {encode name}\r
-  if (s = '.') then begin\r
-    packet.payload[0] := 0;\r
-    result := 12+5;\r
-  end else begin\r
-    for a := 1 to length(s) do begin\r
-      if s[a] = '.' then begin\r
-        if b > maxnamefieldlen then exit;\r
-        if (b = 0) then exit;\r
-        packet.payload[a-b-1] := b;\r
-        b := 0;\r
-      end else begin\r
-        packet.payload[a] := byte(s[a]);\r
-        inc(b);\r
-      end;\r
-    end;\r
-    if b > maxnamefieldlen then exit;\r
-    packet.payload[length(s)-b] := b;\r
-    result := length(s) + 12+5;\r
-  end;\r
-\r
-  arr[result-1] := 1;\r
-  arr[result-3] := requesttype and $ff;\r
-  arr[result-4] := requesttype shr 8;\r
-end;\r
-\r
-function makereversename(const binip:tbinip):string;\r
-var\r
-  name:string;\r
-  a,b:integer;\r
-begin\r
-  name := '';\r
-  if binip.family = AF_INET then begin\r
-    b := htonl(binip.ip);\r
-    for a := 0 to 3 do begin\r
-      name := name + inttostr(b shr (a shl 3) and $ff)+'.';\r
-    end;\r
-    name := name + 'in-addr.arpa';\r
-  end else\r
-  {$ifdef ipv6}\r
-  if binip.family = AF_INET6 then begin\r
-    for a := 15 downto 0 do begin\r
-      b := binip.ip6.u6_addr8[a];\r
-      name := name + hexchars[b and $f]+'.'+hexchars[b shr 4]+'.';\r
-    end;\r
-    name := name + 'ip6.arpa';\r
-  end else\r
-  {$endif}\r
-  begin\r
-    {empty name}\r
-  end;\r
-  result := name;\r
-end;\r
-\r
-{\r
-decodes DNS format name to a string. does not includes the root dot.\r
-doesnt read beyond len.\r
-empty result + non null failurereason: failure\r
-empty result + null failurereason: internal use\r
-}\r
-function decodename(const packet:tdnspacket;len,start,recursion:integer;var numread:integer):string;\r
-var\r
-  arr:array[0..sizeof(packet)-1] of byte absolute packet;\r
-  s:string;\r
-  a,b:integer;\r
-begin\r
-  numread := 0;\r
-  repeat\r
-    if (start+numread < 0) or (start+numread >= len) then begin\r
-      result := '';\r
-      failurereason := 'decoding name: got out of range1';\r
-      exit;\r
-    end;\r
-    b := arr[start+numread];\r
-    if b >= $c0 then begin\r
-      {recursive sub call}\r
-      if recursion > 10 then begin\r
-        result := '';\r
-        failurereason := 'decoding name: max recursion';\r
-        exit;\r
-      end;\r
-      if ((start+numread+1) >= len) then begin\r
-        result := '';\r
-        failurereason := 'decoding name: got out of range3';\r
-        exit;\r
-      end;\r
-      a := ((b shl 8) or arr[start+numread+1]) and $3fff;\r
-      s := decodename(packet,len,a,recursion+1,a);\r
-      if (s = '') and (failurereason <> '') then begin\r
-        result := '';\r
-        exit;\r
-      end;\r
-      if result <> '' then result := result + '.';\r
-      result := result + s;\r
-      inc(numread,2);\r
-      exit;\r
-    end else if b < 64 then begin\r
-      if (numread <> 0) and (b <> 0) then result := result + '.';\r
-      for a := start+numread+1 to start+numread+b do begin\r
-        if (a >= len) then begin\r
-          result := '';\r
-          failurereason := 'decoding name: got out of range2';\r
-          exit;\r
-        end;\r
-        result := result + char(arr[a]);\r
-      end;\r
-      inc(numread,b+1);\r
-\r
-      if b = 0 then begin\r
-        if (result = '') and (recursion = 0) then result := '.';\r
-        exit; {reached end of name}\r
-      end;\r
-    end else begin\r
-      failurereason := 'decoding name: read invalid char';\r
-      result := '';\r
-      exit; {invalid}\r
-    end;\r
-  until false;\r
-end;\r
-\r
-{==============================================================================}\r
-\r
-procedure setstate_return(const rrp:trrpointer;len:integer;var state:tdnsstate);\r
-var\r
-  a:integer;\r
-begin\r
-  state.resultaction := action_done;\r
-  state.resultstr := '';\r
-  case trr(rrp.p^).requesttype of\r
-    querytype_a: begin\r
-      if htons(trr(rrp.p^).datalen) <> 4 then exit;\r
-      move(trr(rrp.p^).data,state.resultbin.ip,4);\r
-      state.resultbin.family :=AF_INET;\r
-    end;\r
-    {$ifdef ipv6}\r
-    querytype_aaaa: begin\r
-      if htons(trr(rrp.p^).datalen) <> 16 then exit;\r
-      state.resultbin.family := AF_INET6;\r
-      move(trr(rrp.p^).data,state.resultbin.ip6,16);\r
-    end;\r
-    {$endif}\r
-  else\r
-    {other reply types (PTR, MX) return a hostname}\r
-    state.resultstr := decodename(state.recvpacket,state.recvpacketlen,taddrint(rrp.p)-taddrint(@state.recvpacket)+10,0,a);\r
-    fillchar(state.resultbin,sizeof(state.resultbin),0);\r
-  end;\r
-end;\r
-\r
-procedure setstate_request_init(const name:string;var state:tdnsstate);\r
-begin\r
-  {destroy things properly}\r
-  state.resultstr := '';\r
-  state.queryname := '';\r
-  state.rrdata := '';\r
-  fillchar(state,sizeof(state),0);\r
-  state.queryname := name;\r
-  state.parsepacket := false;\r
-end;\r
-\r
-procedure setstate_forward(const name:string;var state:tdnsstate;family:integer);\r
-begin\r
-  setstate_request_init(name,state);\r
-  state.forwardfamily := family;\r
-  {$ifdef ipv6}\r
-  if family = AF_INET6 then state.requesttype := querytype_aaaa else\r
-  {$endif}\r
-  state.requesttype := querytype_a;\r
-end;\r
-\r
-procedure setstate_reverse(const binip:tbinip;var state:tdnsstate);\r
-begin\r
-  setstate_request_init(makereversename(binip),state);\r
-  state.requesttype := querytype_ptr;\r
-end;\r
-\r
-procedure setstate_failure(var state:tdnsstate);\r
-begin\r
-  state.resultstr := '';\r
-  fillchar(state.resultbin,sizeof(state.resultbin),0);\r
-  state.resultaction := action_done;\r
-end;\r
-\r
-procedure state_process(var state:tdnsstate);\r
-label recursed;\r
-label failure;\r
-var\r
-  a,b,ofs:integer;\r
-  rrtemp:^trr;\r
-  rrptemp:^trrpointer;\r
-begin\r
-  if state.parsepacket then begin\r
-    if state.recvpacketlen < 12 then begin\r
-      failurereason := 'Undersized packet';\r
-      state.resultaction := action_ignore;\r
-      exit;\r
-    end;\r
-    if state.id <> state.recvpacket.id then begin\r
-      failurereason := 'ID mismatch';\r
-      state.resultaction := action_ignore;\r
-      exit;\r
-    end;\r
-    state.numrr2 := 0;\r
-    for a := 0 to 3 do begin\r
-      state.numrr1[a] := htons(state.recvpacket.rrcount[a]);\r
-      if state.numrr1[a] > maxrrofakind then goto failure;\r
-      inc(state.numrr2,state.numrr1[a]);\r
-    end;\r
-\r
-    setlength(state.rrdata,state.numrr2*sizeof(trrpointer));\r
-\r
-    {- put all replies into a list}\r
-\r
-    ofs := 12;\r
-    {get all queries}\r
-    for a := 0 to state.numrr1[0]-1 do begin\r
-      if (ofs < 12) or (ofs > state.recvpacketlen-4) then goto failure;\r
-      rrptemp := @state.rrdata[1+a*sizeof(trrpointer)];\r
-      rrptemp.p := @state.recvpacket.payload[ofs-12];\r
-      rrptemp.ofs := ofs;\r
-      decodename(state.recvpacket,state.recvpacketlen,ofs,0,b);\r
-      rrptemp.len := b + 4;\r
-      inc(ofs,rrptemp.len);\r
-    end;\r
-\r
-    for a := state.numrr1[0] to state.numrr2-1 do begin\r
-      if (ofs < 12) or (ofs > state.recvpacketlen-12) then goto failure;\r
-      rrptemp := @state.rrdata[1+a*sizeof(trrpointer)];\r
-      if decodename(state.recvpacket,state.recvpacketlen,ofs,0,b) = '' then goto failure;\r
-      rrtemp := @state.recvpacket.payload[ofs-12+b]; {rrtemp points to values and result, after initial name}\r
-      rrptemp.p := rrtemp;\r
-      rrptemp.ofs := ofs; {ofs is start of RR before initial name from start of packet}\r
-      rrptemp.namelen := b;\r
-      b := htons(rrtemp.datalen);\r
-      rrptemp.len := b + 10 + rrptemp.namelen;\r
-      inc(ofs,rrptemp.len);\r
-    end;\r
-    if (ofs <> state.recvpacketlen) then begin\r
-      failurereason := 'ofs <> state.packetlen';\r
-      goto failure;\r
-    end;\r
-\r
-    {- check for items of the requested type in answer section, if so return success first}\r
-    for a := state.numrr1[0] to (state.numrr1[0]+state.numrr1[1]-1) do begin\r
-      rrptemp := @state.rrdata[1+a*sizeof(trrpointer)];\r
-      rrtemp := rrptemp.p;\r
-      b := rrptemp.len;\r
-      if rrtemp.requesttype = state.requesttype then begin\r
-        setstate_return(rrptemp^,b,state);\r
-        exit;\r
-      end;\r
-    end;\r
-\r
-    {if no items of correct type found, follow first cname in answer section}\r
-    for a := state.numrr1[0] to (state.numrr1[0]+state.numrr1[1]-1) do begin\r
-      rrptemp := @state.rrdata[1+a*sizeof(trrpointer)];\r
-      rrtemp := rrptemp.p;\r
-      b := rrptemp.len;\r
-      if rrtemp.requesttype = querytype_cname then begin\r
-        state.queryname := decodename(state.recvpacket,state.recvpacketlen,rrptemp.ofs+12,0,b);\r
-        goto recursed;\r
-      end;\r
-    end;\r
-\r
-    {no cnames found, no items of correct type found}\r
-    if state.forwardfamily <> 0 then goto failure;\r
-{$ifdef ipv6}\r
-    if (state.requesttype = querytype_a) then begin\r
-      {v6 only: in case of forward, look for AAAA in alternative section}\r
-      for a := state.numrr1[0]+state.numrr1[1]+state.numrr1[2] to (state.numrr2-1) do begin\r
-        rrptemp := @state.rrdata[1+a*sizeof(trrpointer)];\r
-        rrtemp := rrptemp.p;\r
-        b := rrptemp.len;\r
-        if rrtemp.requesttype = querytype_aaaa then begin\r
-          setstate_return(rrptemp^,b,state);\r
-          exit;\r
-        end;\r
-      end;\r
-      {no AAAA's found in alternative, do a recursive lookup for them}\r
-      state.requesttype := querytype_aaaa;\r
-      goto recursed;\r
-    end;\r
-{$endif}\r
-    goto failure;\r
-recursed:\r
-    {here it needs recursed lookup}\r
-    {if needing to follow a cname, change state to do so}\r
-    inc(state.recursioncount);\r
-    if state.recursioncount > maxrecursion then goto failure;\r
-  end;\r
-\r
-  {here, a name needs to be resolved}\r
-  if state.queryname = '' then begin\r
-    failurereason := 'empty query name';\r
-    goto failure;\r
-  end;\r
-\r
-  {do /ets/hosts lookup here}\r
-  state.sendpacketlen := buildrequest(state.queryname,state.sendpacket,state.requesttype);\r
-  if state.sendpacketlen = 0 then begin\r
-    failurereason := 'building request packet failed';\r
-    goto failure;\r
-  end;\r
-  state.id := state.sendpacket.id;\r
-  state.resultaction := action_sendquery;\r
-\r
-  exit;\r
-failure:\r
-  setstate_failure(state);\r
-end;\r
-{$ifdef win32}\r
-  const\r
-    MAX_HOSTNAME_LEN = 132;\r
-    MAX_DOMAIN_NAME_LEN = 132;\r
-    MAX_SCOPE_ID_LEN = 260    ;\r
-    MAX_ADAPTER_NAME_LENGTH = 260;\r
-    MAX_ADAPTER_ADDRESS_LENGTH = 8;\r
-    MAX_ADAPTER_DESCRIPTION_LENGTH = 132;\r
-    ERROR_BUFFER_OVERFLOW = 111;\r
-    MIB_IF_TYPE_ETHERNET = 6;\r
-    MIB_IF_TYPE_TOKENRING = 9;\r
-    MIB_IF_TYPE_FDDI = 15;\r
-    MIB_IF_TYPE_PPP = 23;\r
-    MIB_IF_TYPE_LOOPBACK = 24;\r
-    MIB_IF_TYPE_SLIP = 28;\r
-\r
-\r
-  type\r
-    tip_addr_string=packed record\r
-      Next :pointer;\r
-      IpAddress : array[0..15] of char;\r
-      ipmask    : array[0..15] of char;\r
-      context   : dword;\r
-    end;\r
-    pip_addr_string=^tip_addr_string;\r
-    tFIXED_INFO=packed record\r
-       HostName         : array[0..MAX_HOSTNAME_LEN-1] of char;\r
-       DomainName       : array[0..MAX_DOMAIN_NAME_LEN-1] of char;\r
-       currentdnsserver : pip_addr_string;\r
-       dnsserverlist    : tip_addr_string;\r
-       nodetype         : longint;\r
-       ScopeId          : array[0..MAX_SCOPE_ID_LEN + 4] of char;\r
-       enablerouting    : longbool;\r
-       enableproxy      : longbool;\r
-       enabledns        : longbool;\r
-    end;\r
-    pFIXED_INFO=^tFIXED_INFO;\r
-\r
-  var\r
-    iphlpapi : thandle;\r
-    getnetworkparams : function(pFixedInfo : PFIXED_INFO;OutBufLen : plongint) : longint;stdcall;\r
-{$endif}\r
-procedure populatednsserverlist;\r
-var\r
-  {$ifdef win32}\r
-    fixed_info : pfixed_info;\r
-    fixed_info_len : longint;\r
-    currentdnsserver : pip_addr_string;\r
-  {$else}\r
-    t:textfile;\r
-    s:string;\r
-    a:integer;\r
-  {$endif}\r
-begin\r
-  //result := '';\r
-  if assigned(dnsserverlist) then begin\r
-    dnsserverlist.clear;\r
-  end else begin\r
-    dnsserverlist := tstringlist.Create;\r
-  end;\r
-  {$ifdef win32}\r
-    if iphlpapi=0 then iphlpapi := loadlibrary('iphlpapi.dll');\r
-    if not assigned(getnetworkparams) then @getnetworkparams := getprocaddress(iphlpapi,'GetNetworkParams');\r
-    fixed_info_len := 0;\r
-    if GetNetworkParams(nil,@fixed_info_len)<>ERROR_BUFFER_OVERFLOW then exit;\r
-    //fixed_info_len :=sizeof(tfixed_info);\r
-    getmem(fixed_info,fixed_info_len);\r
-    if GetNetworkParams(fixed_info,@fixed_info_len)<>0 then begin\r
-      freemem(fixed_info);\r
-      exit;\r
-    end;\r
-    currentdnsserver := @(fixed_info.dnsserverlist);\r
-    while assigned(currentdnsserver) do begin\r
-      dnsserverlist.Add(currentdnsserver.IpAddress);\r
-      currentdnsserver := currentdnsserver.next;\r
-    end;\r
-    freemem(fixed_info);\r
-  {$else}\r
-    filemode := 0;\r
-    assignfile(t,'/etc/resolv.conf');\r
-    {$i-}reset(t);{$i+}\r
-    if ioresult <> 0 then exit;\r
-\r
-    while not eof(t) do begin\r
-      readln(t,s);\r
-      if not (copy(s,1,10) = 'nameserver') then continue;\r
-      s := copy(s,11,500);\r
-      while s <> '' do begin\r
-        if (s[1] = #32) or (s[1] = #9) then s := copy(s,2,500) else break;\r
-      end;\r
-      a := pos(' ',s);\r
-      if a <> 0 then s := copy(s,1,a-1);\r
-      a := pos(#9,s);\r
-      if a <> 0 then s := copy(s,1,a-1);\r
-      //result := s;\r
-      //if result <> '' then break;\r
-      dnsserverlist.Add(s);\r
-    end;\r
-    close(t);\r
-  {$endif}\r
-end;\r
-\r
-procedure cleardnsservercache;\r
-begin\r
-  if assigned(dnsserverlist) then begin\r
-    dnsserverlist.destroy;\r
-    dnsserverlist := nil;\r
-  end;\r
-end;\r
-\r
-function getcurrentsystemnameserver(var id:integer):string;\r
-var \r
-  counter : integer;\r
-\r
-begin\r
-  if not assigned(dnsserverlist) then populatednsserverlist;\r
-  if dnsserverlist.count=0 then raise exception.create('no dns servers availible');\r
-  id := 0;\r
-  if dnsserverlist.count >1 then begin\r
-\r
-    for counter := 1 to dnsserverlist.count-1 do begin\r
-      if taddrint(dnsserverlist.objects[counter]) < taddrint(dnsserverlist.objects[id]) then id := counter;\r
-    end;\r
-  end;\r
-  result := dnsserverlist[id]\r
-end;\r
-\r
-procedure reportlag(id:integer;lag:integer); //lag should be in microseconds and should be -1 to report a timeout\r
-var\r
-  counter : integer;\r
-  temp : integer;\r
-begin\r
-  if (id < 0) or (id >= dnsserverlist.count) then exit;\r
-  if lag = -1 then lag := timeoutlag;\r
-  for counter := 0 to dnsserverlist.count-1 do begin\r
-    temp := taddrint(dnsserverlist.objects[counter]) *15;\r
-    if counter=id then temp := temp + lag;\r
-    dnsserverlist.objects[counter] := tobject(temp div 16);\r
-  end;\r
-\r
-end;\r
-\r
-{  quick and dirty description of dns packet structure to aid writing and\r
-   understanding of parser code, refer to appropriate RFCs for proper specs\r
-- all words are network order\r
-\r
-www.google.com A request:\r
-\r
-0, 2: random transaction ID\r
-2, 2: flags: only the "recursion desired" bit set. (bit 8 of word)\r
-4, 2: questions: 1\r
-6, 2: answer RR's: 0.\r
-8, 2: authority RR's: 0.\r
-10, 2: additional RR's: 0.\r
-12, n: payload:\r
-  query:\r
-    #03 "www" #06 "google" #03 "com" #00\r
-    size-4, 2: type: host address (1)\r
-    size-2, 2: class: inet (1)\r
-\r
-reply:\r
-\r
-0,2: random transaction ID\r
-2,2: flags: set: response (bit 15), recursion desired (8), recursion available (7)\r
-4,4: questions: 1\r
-6,4: answer RR's: 2\r
-8,4: authority RR's: 9\r
-10,4: additional RR's: 9\r
-12: payload:\r
-  query:\r
-    ....\r
-  answer: CNAME\r
-    0,2 "c0 0c" "name: www.google.com"\r
-    2,2 "00 05" "type: cname for an alias"\r
-    4,2 "00 01" "class: inet"\r
-    6,4: TTL\r
-    10,2: data length "00 17" (23)\r
-    12: the cname name (www.google.akadns.net)\r
-  answer: A\r
-    0,2 ..\r
-    2,2 "00 01" host address\r
-    4,2 ...\r
-    6,4 ...\r
-    10,2: data length (4)\r
-    12,4: binary IP\r
-  authority - 9 records\r
-  additional - 9 records\r
-\r
-\r
-  ipv6 AAAA reply:\r
-    0,2: ...\r
-    2,2: type: 001c\r
-    4,2: class: inet (0001)\r
-    6,2: TTL\r
-    10,2: data size (16)\r
-    12,16: binary IP\r
-\r
-  ptr request: query type 000c\r
-\r
-name compression: word "cxxx" in the name, xxx points to offset in the packet}\r
-\r
-end.\r