X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/85edf7ed5948e0efe59301680f79ea0bac4367e8..HEAD:/lcorelocalips.pas?ds=sidebyside

diff --git a/lcorelocalips.pas b/lcorelocalips.pas
index edd306c..710fbfa 100644
--- a/lcorelocalips.pas
+++ b/lcorelocalips.pas
@@ -53,10 +53,16 @@ function getv6localips:tbiniplist;
 
 function getsystemdnsservers:tbiniplist;
 
+function have_ipv6_connectivity:boolean;
+
 {$ifdef mswindows}
 function gethostname:ansistring;
+function getlocalipforip(const ip:tbinip):tbinip;
 {$endif}
 
+const
+  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.
+
 implementation
 
 {$ifdef unix}
@@ -272,7 +278,7 @@ begin
   end;
 
   try
-    ip := getlocalipforip(ipstrtobinf('2001:200::'));
+    ip := getlocalipforip(ipstrtobinf(v6_check_ip));
     if (ip.family = AF_INET6) then biniplist_add(result,ip);
   except
   end;
@@ -402,6 +408,54 @@ begin
   {$endif}
 end;
 
+
+function have_ipv6_connectivity:boolean;
+var
+  l:tbiniplist;
+  a:integer;
+  ip:tbinip;
+  ipmask_global,ipmask_6to4,ipmask_teredo:tbinip;
+
+function ip_is_suitable_v6:boolean;
+begin
+  result := false;
+  if (ip.family <> AF_INET6) then exit;
+  if not comparebinipmask(ip,ipmask_global,3) then exit;
+  if comparebinipmask(ip,ipmask_teredo,32) then exit;
+  if comparebinipmask(ip,ipmask_6to4,16) then exit;
+  result := true;
+end;
+
+begin
+  result := false;
+
+  ipstrtobin('2000::',ipmask_global);
+  ipstrtobin('2001::',ipmask_teredo);
+  ipstrtobin('2002::',ipmask_6to4);
+
+  {$ifdef mswindows}
+  //better way on windows to check for ipv6 that works (returns no ipv6) if a v6 IP is assigned, but there is no connectivity
+  try
+    ip := getlocalipforip(ipstrtobinf(v6_check_ip));
+    if ip_is_suitable_v6 then result := true;
+  except
+  end;
+  {$else} {unix}
+
+  l := getv6localips;
+  if biniplist_getcount(l) = 0 then exit;
+
+  {if there is any v6 IP which is globally routable and not 6to4 and not teredo, prefer v6}
+  for a := biniplist_getcount(l)-1 downto 0 do begin
+    ip := biniplist_get(l,a);
+    if not ip_is_suitable_v6 then continue;
+    result := true;
+    exit;
+  end;
+  {$endif}
+end;
+
+
 {$ifdef mswindows}
 function gethostname:ansistring;
 var
@@ -419,4 +473,3 @@ end;
 {$endif}
 
 end.
-