From 2be79db6f8dcdcfd1e23d7c197bfcec61c8dcd61 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Tue, 18 Jul 2023 13:53:48 +0200 Subject: [PATCH] interfaces: introduce a lock and DAD timer into newwanip for IPv6 #6637 There seem to be two issues: 1. Tentative addresses could have always been ignored for the wrong reasons and we can savely move the delay to this script even though a small delay will be the result (2 seconds with the default sysctl). Not sure why this problem previously not mattered that much, but at least we can move the other instance of the delay to here and avoid duplication since it will continue to load this script anyway. 2. Due to overlaps and technical convolution these scripts can be run multile times in a very short succession especially on a bootup. Since we have a delay here now we force a lock prior to "catch" stray invocations. The only issue I see is that we could lose the "force" flag in the process, but if that is the case the log message will reveal and we can work around this sas well with a two stage log perhaps. --- src/etc/rc.newwanipv6 | 18 ++++++++++++++++-- .../scripts/interfaces/rtsold_resolvconf.sh | 3 --- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/etc/rc.newwanipv6 b/src/etc/rc.newwanipv6 index 7a03d1652..7c3831a10 100755 --- a/src/etc/rc.newwanipv6 +++ b/src/etc/rc.newwanipv6 @@ -58,12 +58,26 @@ if (!isset($config['interfaces'][$interface]['enable'])) { return; } +$interface_descr = convert_friendly_interface_to_friendly_descr($interface); + +/* make sure only one script runs at a time beyond this point */ +$fp = fopen('/tmp/newwanipv6_' . $argument, 'a+'); +if (!$fp || !flock($fp, LOCK_EX | LOCK_NB)) { + if ($force == 'yes') { + log_msg("Lost a forceful reload on {$interface_descr}[{$interface}]) due to previous lock", LOG_WARNING); + } + fclose($fp); + return; +} + +/* wait for DAD to complete to avoid discarding tentative address */ +$dad_delay = (int)get_single_sysctl('net.inet6.ip6.dad_count'); +sleep($dad_delay + 1); + /* this may be required to cleanse the DNS information no longer available */ system_resolver_configure(); -$interface_descr = convert_friendly_interface_to_friendly_descr($interface); list ($ip) = interfaces_primary_address6($interface); - if (!is_ipaddr($ip)) { /* interface is not ready */ log_msg("Failed to detect IP for {$interface_descr}[{$interface}]", LOG_INFO); diff --git a/src/opnsense/scripts/interfaces/rtsold_resolvconf.sh b/src/opnsense/scripts/interfaces/rtsold_resolvconf.sh index 96ac162ba..bd32e051a 100755 --- a/src/opnsense/scripts/interfaces/rtsold_resolvconf.sh +++ b/src/opnsense/scripts/interfaces/rtsold_resolvconf.sh @@ -69,8 +69,5 @@ elif [ "${1}" = "-d" ]; then /usr/local/sbin/ifctl -i ${ifname} -6rd fi -# wait for DAD to complete to avoid tentative address -sleep "$(($(sysctl -n net.inet6.ip6.dad_count) + 1))" - # remove slaac suffix here to reload correct interface /usr/local/sbin/configctl -d interface newipv6 ${ifname%%:slaac}