X-Git-Url: http://www.lcore.org/git/lcore.git/blobdiff_plain/3ac664ec654230b9ad26ab12242c1db6f636a26f..a77cd534c22418ec9a8a22ae42efef1a9500b193:/lcorelocalips.pas diff --git a/lcorelocalips.pas b/lcorelocalips.pas index ae2a00b..710fbfa 100644 --- a/lcorelocalips.pas +++ b/lcorelocalips.pas @@ -36,7 +36,9 @@ notes: } unit lcorelocalips; - +{$ifdef fpc} + {$mode delphi} +{$endif} interface uses binipstuff,pgtypes; @@ -51,10 +53,16 @@ function getv6localips:tbiniplist; function getsystemdnsservers:tbiniplist; -{$ifdef win32} +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} @@ -188,7 +196,7 @@ end; {$else} uses - sysutils,windows,winsock,dnssync; + sysutils,windows,winsock,dnswin; {the following code's purpose is to determine what IP windows would come from, to reach an IP it can be abused to find if there's any global v6 IPs on a local interface} @@ -255,8 +263,10 @@ function getlocalips:tbiniplist; var a:integer; ip:tbinip; + usewindnstemp:boolean; + error:integer; begin - result := forwardlookuplist('',0); + result := winforwardlookuplist('',0,error); {$ifdef ipv6} @@ -268,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; @@ -282,7 +292,7 @@ end; -{$ifdef win32} +{$ifdef mswindows} const MAX_HOSTNAME_LEN = 132; MAX_DOMAIN_NAME_LEN = 132; @@ -348,7 +358,7 @@ end; function getsystemdnsservers:tbiniplist; var - {$ifdef win32} + {$ifdef mswindows} fixed_info : pfixed_info; currentdnsserver : pip_addr_string; {$else} @@ -362,7 +372,7 @@ begin result := biniplist_new; - {$ifdef win32} + {$ifdef mswindows} fixed_info := callgetnetworkparams; if fixed_info = nil then exit; @@ -398,7 +408,55 @@ begin {$endif} end; -{$ifdef win32} + +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 fixed_info : pfixed_info;