move ipv6 connectivity check from dnscore init to a reusable function in lcorelocalips
authorbeware <beware@bircd.org>
Wed, 15 Mar 2023 16:27:46 +0000 (16:27 +0000)
committerbeware <beware@bircd.org>
Wed, 15 Mar 2023 16:32:47 +0000 (16:32 +0000)
dnscore.pas
lcorelocalips.pas

index e38f35f9295cdbad4ba6c3507e171abfcd3b2ea1..08f99d1c87180bd0b3cc351f84d68c988db0efca 100644 (file)
@@ -684,31 +684,16 @@ end;
 {$ifdef ipv6}\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
-  l := getv6localips;\r
-  if biniplist_getcount(l) = 0 then exit;\r
-  useaf := useaf_preferv4;\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
+\r
+  if (have_ipv6_connectivity) then\r
+    useaf := useaf_preferv6\r
+  else\r
+    useaf := useaf_preferv4;\r
+\r
+  preferredmodeinited := true;\r
 end;\r
 \r
 {$endif}\r
index edd306ce4cd8ad836c615286d659a79b5fc8b5a8..710fbfa4070d8d360da589557ad95c5932a8ce82 100644 (file)
@@ -53,10 +53,16 @@ function getv6localips:tbiniplist;
 \r
 function getsystemdnsservers:tbiniplist;\r
 \r
+function have_ipv6_connectivity:boolean;\r
+\r
 {$ifdef mswindows}\r
 function gethostname:ansistring;\r
+function getlocalipforip(const ip:tbinip):tbinip;\r
 {$endif}\r
 \r
+const\r
+  v6_check_ip='2001:200::';  //a globally routeable v6 IP that is used in "get local IP for IP" etc, it should never actually be communicated with.\r
+\r
 implementation\r
 \r
 {$ifdef unix}\r
@@ -272,7 +278,7 @@ begin
   end;\r
 \r
   try\r
-    ip := getlocalipforip(ipstrtobinf('2001:200::'));\r
+    ip := getlocalipforip(ipstrtobinf(v6_check_ip));\r
     if (ip.family = AF_INET6) then biniplist_add(result,ip);\r
   except\r
   end;\r
@@ -402,6 +408,54 @@ begin
   {$endif}\r
 end;\r
 \r
+\r
+function have_ipv6_connectivity:boolean;\r
+var\r
+  l:tbiniplist;\r
+  a:integer;\r
+  ip:tbinip;\r
+  ipmask_global,ipmask_6to4,ipmask_teredo:tbinip;\r
+\r
+function ip_is_suitable_v6:boolean;\r
+begin\r
+  result := false;\r
+  if (ip.family <> AF_INET6) then exit;\r
+  if not comparebinipmask(ip,ipmask_global,3) then exit;\r
+  if comparebinipmask(ip,ipmask_teredo,32) then exit;\r
+  if comparebinipmask(ip,ipmask_6to4,16) then exit;\r
+  result := true;\r
+end;\r
+\r
+begin\r
+  result := false;\r
+\r
+  ipstrtobin('2000::',ipmask_global);\r
+  ipstrtobin('2001::',ipmask_teredo);\r
+  ipstrtobin('2002::',ipmask_6to4);\r
+\r
+  {$ifdef mswindows}\r
+  //better way on windows to check for ipv6 that works (returns no ipv6) if a v6 IP is assigned, but there is no connectivity\r
+  try\r
+    ip := getlocalipforip(ipstrtobinf(v6_check_ip));\r
+    if ip_is_suitable_v6 then result := true;\r
+  except\r
+  end;\r
+  {$else} {unix}\r
+\r
+  l := getv6localips;\r
+  if biniplist_getcount(l) = 0 then exit;\r
+\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 ip_is_suitable_v6 then continue;\r
+    result := true;\r
+    exit;\r
+  end;\r
+  {$endif}\r
+end;\r
+\r
+\r
 {$ifdef mswindows}\r
 function gethostname:ansistring;\r
 var\r
@@ -419,4 +473,3 @@ end;
 {$endif}\r
 \r
 end.\r
-\r