}\r
\r
unit lcorelocalips;\r
-\r
+{$ifdef fpc}\r
+ {$mode delphi}\r
+{$endif}\r
interface\r
\r
uses binipstuff,pgtypes;\r
\r
function getsystemdnsservers:tbiniplist;\r
\r
-{$ifdef win32}\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
{$else}\r
\r
uses\r
- sysutils,windows,winsock,dnssync;\r
+ sysutils,windows,winsock,dnswin;\r
\r
{the following code's purpose is to determine what IP windows would come from, to reach an IP\r
it can be abused to find if there's any global v6 IPs on a local interface}\r
var\r
a:integer;\r
ip:tbinip;\r
+ usewindnstemp:boolean;\r
+ error:integer;\r
begin\r
- result := forwardlookuplist('',0);\r
+ result := winforwardlookuplist('',0,error);\r
\r
{$ifdef ipv6}\r
\r
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
\r
\r
\r
-{$ifdef win32}\r
+{$ifdef mswindows}\r
const\r
MAX_HOSTNAME_LEN = 132;\r
MAX_DOMAIN_NAME_LEN = 132;\r
\r
function getsystemdnsservers:tbiniplist;\r
var\r
- {$ifdef win32}\r
+ {$ifdef mswindows}\r
fixed_info : pfixed_info;\r
currentdnsserver : pip_addr_string;\r
{$else}\r
\r
result := biniplist_new;\r
\r
- {$ifdef win32}\r
+ {$ifdef mswindows}\r
fixed_info := callgetnetworkparams;\r
if fixed_info = nil then exit;\r
\r
{$endif}\r
end;\r
\r
-{$ifdef win32}\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
fixed_info : pfixed_info;\r