Merged with delphi 2010 branch
[lcore.git] / dnssync.pas
old mode 100755 (executable)
new mode 100644 (file)
index 3632b29..7d6631c
@@ -25,33 +25,28 @@ interface
       sockets,\r
       fd_utils,\r
     {$endif}\r
-    sysutils;\r
+    lcorernd,\r
+    sysutils,\r
+    ltimevalstuff;\r
 \r
 //convert a name to an IP\r
 //will return v4 or v6 depending on what seems favorable, or manual preference setting\r
 //on error the binip will have a family of 0 (other fiels are also currently\r
 //zeroed out but may be used for further error information in future)\r
 //timeout is in miliseconds, it is ignored when using windows dns\r
-function forwardlookup(name:string;timeout:integer):tbinip;\r
+function forwardlookup(name:ansistring;timeout:integer):tbinip;\r
 \r
 //convert a name to a list of all IP's returned\r
 //this returns both v4 and v6 IP's, or possibly only v4 or v6, depending on settings\r
 //on error, returns an empty list\r
-function forwardlookuplist(name:string;timeout:integer):tbiniplist;\r
+function forwardlookuplist(name:ansistring;timeout:integer):tbiniplist;\r
 \r
 \r
 //convert an IP to a name, on error a null string will be returned, other\r
 //details as above\r
-function reverselookup(ip:tbinip;timeout:integer):string;\r
+function reverselookup(ip:tbinip;timeout:integer):ansistring;\r
 \r
-{$ifdef linux}{$ifdef ipv6}\r
-function getv6localips:tbiniplist;\r
-procedure initpreferredmode;\r
 \r
-var\r
-  preferredmodeinited:boolean;\r
-\r
-{$endif}{$endif}\r
 \r
 const\r
   tswrap=$4000;\r
@@ -61,8 +56,9 @@ const
   defaulttimeout=10000;\r
   const mintimeout=16;\r
 \r
+  toport='53';\r
+\r
 var\r
-  dnssyncserver:string;\r
   id:integer;\r
 \r
   sendquerytime:array[0..numsock-1] of integer;\r
@@ -78,12 +74,12 @@ implementation
 {$endif}\r
 \r
 {$i unixstuff.inc}\r
-{$i ltimevalstuff.inc}\r
 \r
 var\r
   numsockused:integer;\r
   fd:array[0..numsock-1] of integer;\r
   state:array[0..numsock-1] of tdnsstate;\r
+  toaddr:array[0..numsock-1] of tbinip;\r
 \r
 {$ifdef syncdnscore}\r
 \r
@@ -114,18 +110,23 @@ end;
 function sendquery(socknum:integer;const packet:tdnspacket;len:integer):boolean;\r
 var\r
   a:integer;\r
-  addr       : string;\r
-  port       : string;\r
+  addr       : ansistring;\r
+  port       : ansistring;\r
   inaddr     : TInetSockAddrV;\r
 begin\r
 {  writeln('sendquery ',decodename(state.packet,state.packetlen,12,0,a),' ',state.requesttype);}\r
   result := false;\r
   if len = 0 then exit; {no packet}\r
 \r
-  if dnssyncserver <> '' then addr := dnssyncserver else addr := getcurrentsystemnameserver(id);\r
-  port := '53';\r
+  if overridednsserver <> '' then addr := overridednsserver else addr := getcurrentsystemnameserver(id);\r
 \r
-  makeinaddrv(ipstrtobinf(addr),port,inaddr);\r
+  {$ifdef ipv6}{$ifdef win32}\r
+  if toaddr[socknum].family = AF_INET6 then if (useaf = 0) then useaf := useaf_preferv6;\r
+  {$endif}{$endif}\r
+\r
+  port := toport;\r
+  toaddr[socknum] := ipstrtobinf(addr);\r
+  makeinaddrv(toaddr[socknum],port,inaddr);\r
 \r
   sendto(fd[socknum],packet,len,0,inaddr,inaddrsize(inaddr));\r
   sendquerytime[socknum] := getts;\r
@@ -137,21 +138,22 @@ var
   inAddrtemp : TInetSockAddrV;\r
   a:integer;\r
   biniptemp:tbinip;\r
-  addr:string;\r
+  addr:ansistring;\r
 begin\r
   //init both sockets smultaneously, always, so they get succesive fd's\r
   if fd[0] > 0 then exit;\r
 \r
-  if dnssyncserver <> '' then addr := dnssyncserver else addr := getcurrentsystemnameserver(id);\r
+  if overridednsserver <> '' then addr := overridednsserver else addr := getcurrentsystemnameserver(id);\r
   //must get the DNS server here so we know to init v4 or v6\r
 \r
-  fillchar(inaddrtemp,sizeof(inaddrtemp),0);\r
   ipstrtobin(addr,biniptemp);\r
-  if biniptemp.family = 0 then biniptemp.family := AF_INET;\r
 \r
-  inaddrtemp.inaddr.family := biniptemp.family;\r
+  if biniptemp.family = AF_INET6 then biniptemp := ipstrtobinf('::') else biniptemp := ipstrtobinf('0.0.0.0');\r
+\r
 \r
   for a := 0 to numsockused-1 do begin\r
+    makeinaddrv(biniptemp,inttostr( 1024 + randominteger(65536 - 1024) ),inaddrtemp);\r
+\r
     fd[a] := Socket(biniptemp.family,SOCK_DGRAM,0);\r
 \r
     If {$ifndef win32}Not{$endif} Bind(fd[a],inAddrtemp,inaddrsize(inaddrtemp)) Then begin\r
@@ -182,6 +184,12 @@ var
   finished:array[0..numsock-1] of boolean;\r
   a,b:integer;\r
 \r
+  Src    : TInetSockAddrV;\r
+  Srcx   : {$ifdef win32}sockaddr_in{$else}TInetSockAddrV{$endif} absolute Src;\r
+  SrcLen : Integer;\r
+  fromip:tbinip;\r
+  fromport:ansistring;\r
+\r
 begin\r
   if timeout < mintimeout then timeout := defaulttimeout;\r
 \r
@@ -249,10 +257,22 @@ begin
         fillchar(state[socknum].recvpacket,sizeof(state[socknum].recvpacket),0);\r
         msectotimeval(lag,(currenttime-sendquerytime[socknum]) and tsmask);\r
 \r
-        if dnssyncserver = '' then reportlag(id,(lag.tv_sec*1000000)+lag.tv_usec);\r
-        state[socknum].recvpacketlen := recv(fd[socknum],state[socknum].recvpacket, SizeOf(state[socknum].recvpacket),0);\r
-        state[socknum].parsepacket := true;\r
-        needprocessing[socknum] := true;\r
+        if overridednsserver = '' then reportlag(id,(lag.tv_sec*1000000)+lag.tv_usec);\r
+\r
+        SrcLen := SizeOf(Src);\r
+        state[socknum].recvpacketlen := recvfrom(fd[socknum],state[socknum].recvpacket, SizeOf(state[socknum].recvpacket),0,Srcx,SrcLen);\r
+\r
+        if (state[socknum].recvpacketlen > 0) then begin\r
+          fromip := inaddrvtobinip(Src);\r
+          fromport := inttostr(htons(src.InAddr.port));\r
+          if ((not comparebinip(toaddr[socknum],fromip)) or (fromport <> toport)) then begin\r
+//            writeln('dnssync received from wrong IP:port ',ipbintostr(fromip),'#',fromport);\r
+            state[socknum].recvpacketlen := 0;\r
+          end else begin\r
+            state[socknum].parsepacket := true;\r
+            needprocessing[socknum] := true;\r
+          end;\r
+        end;\r
       end;\r
     end;\r
     if selectresult < 0 then exit;\r
@@ -260,7 +280,7 @@ begin
 \r
       currenttime := getts;\r
 \r
-      if dnssyncserver = '' then reportlag(id,-1);\r
+      if overridednsserver = '' then reportlag(id,-1);\r
       if (currenttime >= endtime) and ((not wrapmode) or (currenttime < starttime)) then begin\r
         exit;\r
       end else begin\r
@@ -274,19 +294,9 @@ begin
 end;\r
 {$endif}\r
 \r
-procedure addipsoffamily(var l:tbiniplist;const l2:tbiniplist;family:integer);\r
-var\r
-  a:integer;\r
-  biniptemp:tbinip;\r
-begin\r
-  for a := biniplist_getcount(l2)-1 downto 0 do begin\r
-    biniptemp := biniplist_get(l2,a);\r
-    if (biniptemp.family = family) then biniplist_add(l,biniptemp);\r
-  end;\r
-end;\r
 \r
 \r
-function forwardlookuplist(name:string;timeout:integer):tbiniplist;\r
+function forwardlookuplist(name:ansistring;timeout:integer):tbiniplist;\r
 var\r
   dummy : integer;\r
   a,b:integer;\r
@@ -324,7 +334,7 @@ begin
   {$endif}\r
   begin\r
   {$ifdef syncdnscore}\r
-    {$ifdef linux}{$ifdef ipv6}initpreferredmode;{$endif}{$endif}\r
+    {$ifdef ipv6}initpreferredmode;{$endif}\r
 \r
     numsockused := 0;\r
 \r
@@ -351,13 +361,13 @@ begin
     end else begin\r
       biniplist_addlist(result,state[0].resultlist);\r
       biniplist_addlist(result,state[1].resultlist);\r
-    {$endif}  \r
+    {$endif}\r
     end;\r
     {$endif}\r
   end;\r
 end;\r
 \r
-function forwardlookup(name:string;timeout:integer):tbinip;\r
+function forwardlookup(name:ansistring;timeout:integer):tbinip;\r
 var\r
   listtemp:tbiniplist;\r
 begin\r
@@ -365,7 +375,7 @@ begin
   result := biniplist_get(listtemp,0);\r
 end;\r
 \r
-function reverselookup(ip:tbinip;timeout:integer):string;\r
+function reverselookup(ip:tbinip;timeout:integer):ansistring;\r
 var\r
   dummy : integer;\r
 begin\r
@@ -383,62 +393,6 @@ begin
   {$endif}\r
 end;\r
 \r
-{$ifdef linux}{$ifdef ipv6}{$ifdef syncdnscore}\r
-function getv6localips:tbiniplist;\r
-var\r
-  t:textfile;\r
-  s,s2:string;\r
-  ip:tbinip;\r
-  a:integer;\r
-begin\r
-  result := biniplist_new;\r
-\r
-  assignfile(t,'/proc/net/if_inet6');\r
-  {$i-}reset(t);{$i+}\r
-  if ioresult <> 0 then exit; {none found, return empty list}\r
-\r
-  while not eof(t) do begin\r
-    readln(t,s);\r
-    s2 := '';\r
-    for a := 0 to 7 do begin\r
-      if (s2 <> '') then s2 := s2 + ':';\r
-      s2 := s2 + copy(s,(a shl 2)+1,4);\r
-    end;\r
-    ipstrtobin(s2,ip);\r
-    if ip.family <> 0 then biniplist_add(result,ip);\r
-  end;\r
-  closefile(t);\r
-end;\r
-\r
-procedure initpreferredmode;\r
-var\r
-  l:tbiniplist;\r
-  a:integer;\r
-  ip:tbinip;\r
-  ipmask_global,ipmask_6to4,ipmask_teredo:tbinip;\r
-\r
-begin\r
-  if preferredmodeinited then exit;\r
-  if useaf <> useaf_default then exit;\r
-  useaf := useaf_preferv4;\r
-  l := getv6localips;\r
-  ipstrtobin('2000::',ipmask_global);\r
-  ipstrtobin('2001::',ipmask_teredo);\r
-  ipstrtobin('2002::',ipmask_6to4);\r
-  {if there is any v6 IP which is globally routable and not 6to4 and not teredo, prefer v6}\r
-  for a := biniplist_getcount(l)-1 downto 0 do begin\r
-    ip := biniplist_get(l,a);\r
-    if not comparebinipmask(ip,ipmask_global,3) then continue;\r
-    if comparebinipmask(ip,ipmask_teredo,32) then continue;\r
-    if comparebinipmask(ip,ipmask_6to4,16) then continue;\r
-    useaf := useaf_preferv6;\r
-    preferredmodeinited := true;\r
-    exit;\r
-  end;\r
-end;\r
-\r
-{$endif}{$endif}{$endif}\r
-\r
 {$ifdef win32}\r
   var\r
     wsadata : twsadata;\r