From b60a32da0a15deb572474b1f66a6c63695ed7491 Mon Sep 17 00:00:00 2001 From: beware Date: Wed, 15 Mar 2023 16:27:46 +0000 Subject: [PATCH] move ipv6 connectivity check from dnscore init to a reusable function in lcorelocalips --- dnscore.pas | 29 ++++++------------------ lcorelocalips.pas | 57 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/dnscore.pas b/dnscore.pas index e38f35f..08f99d1 100644 --- a/dnscore.pas +++ b/dnscore.pas @@ -684,31 +684,16 @@ end; {$ifdef ipv6} procedure initpreferredmode; -var - l:tbiniplist; - a:integer; - ip:tbinip; - ipmask_global,ipmask_6to4,ipmask_teredo:tbinip; - begin if preferredmodeinited then exit; if useaf <> useaf_default then exit; - l := getv6localips; - if biniplist_getcount(l) = 0 then exit; - useaf := useaf_preferv4; - ipstrtobin('2000::',ipmask_global); - ipstrtobin('2001::',ipmask_teredo); - ipstrtobin('2002::',ipmask_6to4); - {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 comparebinipmask(ip,ipmask_global,3) then continue; - if comparebinipmask(ip,ipmask_teredo,32) then continue; - if comparebinipmask(ip,ipmask_6to4,16) then continue; - useaf := useaf_preferv6; - preferredmodeinited := true; - exit; - end; + + if (have_ipv6_connectivity) then + useaf := useaf_preferv6 + else + useaf := useaf_preferv4; + + preferredmodeinited := true; end; {$endif} 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. - -- 2.30.2