summaryrefslogtreecommitdiffstats
path: root/src/etc/inc/interfaces.inc
diff options
context:
space:
mode:
authormarjohn56 <martin@queens-park.com>2017-02-08 22:49:52 +0000
committermarjohn56 <martin@queens-park.com>2017-03-08 08:42:00 +0000
commit718cbc2d3921627e9767e59d539386c843dffcc4 (patch)
treec8a4b07d5ae0cf1023ca354d06fe9b92a1b375cc /src/etc/inc/interfaces.inc
parentf0136b178022cf3b04a6c3d577d457cf3bc03418 (diff)
downloadpfsense-718cbc2d3921627e9767e59d539386c843dffcc4.zip
pfsense-718cbc2d3921627e9767e59d539386c843dffcc4.tar.gz
New dhcp6c features REASONS and signals
This PR takes advantage of modifications and additions to dhcp6c. Firstly, a fix has been made to dhcp6c where the pid was being deleted before all processes had completed; this could leave dhcp6c sending release signals but any check for the process using the pid would return false; thus if the server was not responding or the WAN was down then dhcp6c could sit there for tens of seconds even though it appeared to have exited. The env var REASON has been updated to provide information as to why the script has been called. These can be one of the following: REASON=INFO REASON=REPLY REASON=RENEW REASON=RELEASE REASON=REBIND REASON=EXIT REASON=OTHER The OTHER is a final catch and should never happen. The scripts take advantage of these vars, for example a renew no longer calls rc.newwanipv6. The use of SIGUSR1 and SIGUSR2 to terminate dhcp6c results in different exits. SIGUSR1 will force an exit without sending a release to the server, this is used in the case of a WAN down event to prevent dhcp6c from hanging on a release signal. SIGUSR2 is used to send a relase signal overiding the no-release flag ( if set ), no code or GUI additions have been added to make use of this signal in this PR. The existing SIGTERM will cause dhcp6c to exit normally obeying the no-release flag if set. NOTE - The code for SIGUSR2 is in place in this file but as yet it is not included in dhcp6c. In the event of SIGUSR2 being called, it will fall through to a standard SIGTERM exit. Debugging messages have been added to the scripts dhcp6c_{$interface}dhcp6withoutra_script.sh and dhcp6c{$interface}_script.sh. These debug messages only appear if the debug setting for dhcp6c has been set in the config, they also appear in the dhcp log rather than the main system log. This PR is dependant on PR#5 at hrs-allbsd:freebsd or pfsense/FreeBSD-ports #299 These changes are in response to Redmine 5993, 6944, 7145 and 7185. Updated to match new upstream dhcp6c changed REASON=REPLY to REASON=REQUEST. K&R Corrections
Diffstat (limited to 'src/etc/inc/interfaces.inc')
-rw-r--r--src/etc/inc/interfaces.inc179
1 files changed, 137 insertions, 42 deletions
diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc
index 74a8a33..273b8ff 100644
--- a/src/etc/inc/interfaces.inc
+++ b/src/etc/inc/interfaces.inc
@@ -1300,7 +1300,7 @@ function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg =
switch ($ifcfg['ipaddrv6']) {
case "slaac":
case "dhcp6":
- kill_dhcp6client_process($realif, isset($ifcfg['dhcp6norelease']));
+ kill_dhcp6client_process($realif, $destroy, false);
unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh");
unlink_if_exists("{$g['varetc_path']}/rtsold_{$realifv6}_script.sh");
@@ -3039,33 +3039,61 @@ function find_dhcp6c_process($interface) {
return intval($pid);
}
-function kill_dhcp6client_process($interface, $norelease) {
+function kill_dhcp6client_process($interface, $force, $release = false) {
global $g;
+ $i = 0;
+
+ /*
+ Beware of the following: Reason, the interface may be down, but
+ dhcp6c may still be running, it just complains it cannot send
+ and carries on. Commented out as will stop the call to kill.
+
if (empty($interface) || !does_interface_exist($interface)) {
return;
}
+ */
- if (($pid = find_dhcp6c_process($interface)) != 0) {
- /*
- * Kill -9 caused the pid to get left behind, also if we need a
- * relase sent then it needs to be -15, this then allows dhcp6c
- * to send the release, it will also clean up after itself
- */
- $sig = (isset($norelease) ? SIGKILL : SIGTERM);
- posix_kill($pid, $sig);
- if(!isset($norelease)) {
- /*
- * Allow dhcp6c to send release and exit gracefully if
- * needed.
- */
- sleep(2);
- }
+ /*********** Notes on signals for dhcp6c and this function *************
+
+ If we have Taken the WAN interface down, then dhcp6c sits there sending
+ a release and waiting for the response that never comes.
+ So we need to tell it that the interface is down and to just die quickly
+ otherwise a new client may launch and we have duplicate proceses.
+ In this case use SIGUSR1.
+
+ If we want to exit normally obeying the no release flag then use SIGTERM.
+ If we want to exit with a release overiding the no release flag then
+ use SIGUSR2.
+
+ If $Force is true it will use SIGUSR1, thus forcing dhcp6c to
+ exit quickly without sending release signals.
+
+ If $Force is set to false and $release is also set to false dhcp6c will
+ follow the no-release flag.
+
+ If $Force is set to false and $release is true then dhcp6c will send a
+ release regardless of the no-release flag.
+ ***********************************************************************/
+
+ if ($force == true) {
+ $psig=SIGUSR1;
+ } else if ($release == false) {
+ $psig=SIGTERM;
+ } else {
+ $psig=SIGUSR2;
}
- /* Clear the RTSOLD script created lock & tidy up */
+
+ while ((($pid = find_dhcp6c_process($interface)) != 0) && ($i < 3)) {
+ /* 3rd time make it die for sure */
+ $sig = ($i == 2 ? SIGKILL : $psig);
+ posix_kill($pid, $sig);
+ sleep(1);
+ $i++;
+ }
+ /* Clear the RTSOLD script created lock & tidy up */
unlink_if_exists("/tmp/dhcp6c_{$interface}_lock");
- /* just in case! */
- unlink_if_exists("{$g['varrun_path']}/dhcp6c_{$interface}.pid");
+ unlink_if_exists("{$g['varrun_path']}/dhcp6c_{$interface}.pid"); // just in case!
}
function run_dhcp6client_process($interface, $wancfg) {
@@ -3083,8 +3111,7 @@ function run_dhcp6client_process($interface, $wancfg) {
* lock deleted.
*/
if (!file_exists("/tmp/dhcp6c_{$interface}_lock")) {
- kill_dhcp6client_process($interface,
- isset($wancfg['dhcp6norelease']));
+ kill_dhcp6client_process($realif, true);
/* Lock it to avoid multiple runs */
touch("/tmp/dhcp6c_{$interface}_lock");
@@ -3940,6 +3967,13 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
log_error(gettext("Failed to write user DUID file!"));
}
}
+
+ /* accept router advertisements for this interface */
+ /* Moved to early in the function as sometimes interface not ready */
+ /* RTSOLD fails as interface does not accept ..... */
+
+ log_error("Accept router advertisements on interface {$wanif} ");
+ mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
if ($wancfg['adv_dhcp6_config_file_override']) {
// DHCP6 Config File Override
@@ -4017,6 +4051,9 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
}
}
+ $debugOption = isset($wancfg['dhcp6debug']) ? "-D" : "-d";
+ $noreleaseOption = isset($wancfg['dhcp6norelease']) ? "-n" : "";
+
/* wide-dhcp6c works for now. */
if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
@@ -4025,20 +4062,55 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
}
unset($dhcp6cconf);
- /*
- * Script create for dhcp6withoutRA mode.
- * dhcp6c will launch rtsold. rtsold will then run the wan ipv6
- * configure
- */
- $dhcp6cscriptwithoutra = "#!/bin/sh\n";
+ /*************** Script Debug Logging ***************************
+ Both dhcp6 scripts now have a logging message built in.
+ These logging messages ONLY appear if dhcp6c debug logging is set.
+ The logging messages appear in the dhcp section of the logs,
+ not in system.
+
+ These scripts now also take advantage of the REASON= env vars
+ supplied by dhcp6c.
+ ****************************************************************/
+
+ /* Script create for dhcp6withoutRA mode */
+ /* dhcp6c will launch rtsold. rtsold will then run the wan ipv6 configure */
+ $dhcp6cscriptwithoutra = "#!/bin/sh\n";
$dhcp6cscriptwithoutra .= "# This shell script launches rtsold.\n";
$dhcp6cscriptwithoutra .= "dmips=\${new_domain_name_servers}\n";
$dhcp6cscriptwithoutra .= "dmnames=\${new_domain_name}\n";
+ $dhcp6cscriptwithoutra .= "dreason=\${REASON}\n";
// Need to pass params to the final script
$dhcp6cscriptwithoutra .= "echo \$dmips > /tmp/{$wanif}_domain_name_servers\n";
$dhcp6cscriptwithoutra .= "echo \$dmnames > /tmp/{$wanif}_new_domain_name\n";
+ $dhcp6cscriptwithoutra .= "echo \$dreason > /tmp/{$wanif}_reason\n";
+ $dhcp6cscriptwithoutra .= "case \$REASON in\n";
+ $dhcp6cscriptwithoutra .= "REQUEST)\n";
+ $dhcp6cscriptwithoutra .= "/bin/sleep 2\n";
$dhcp6cscriptwithoutra .= "/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}\n";
-
+ if ($debugOption == '-D') {
+ $dhcp6cscriptwithoutra .= "/usr/bin/logger -t dhcp6c \"dhcp6c REQUEST on {$wanif} - running rc.newwanipv6\"\n";
+ }
+ $dhcp6cscriptwithoutra .= ";;\n";
+ $dhcp6cscriptwithoutra .= "REBIND)\n";
+ if ($debugOption == '-D') {
+ $dhcp6cscriptwithoutra .= "/usr/bin/logger -t dhcp6c \"dhcp6c rebind on {$wanif}\"\n";
+ }
+ $dhcp6cscriptwithoutra .= ";;\n";
+ if (isset($wancfg['dhcp6norelease'])) {
+ $dhcp6cscriptwithoutra .= "EXIT)\n";
+ } else {
+ $dhcp6cscriptwithoutra .= "RELEASE)\n";
+ }
+ if ($debugOption == '-D') {
+ $dhcp6cscriptwithoutra .= "/usr/bin/logger -t dhcp6c \"dhcp6c EXIT or RELEASE on {$wanif} running rc.newwanipv6\"\n";
+ }
+ $dhcp6cscriptwithoutra .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
+ $dhcp6cscriptwithoutra .= ";;\n";
+ $dhcp6cscriptwithoutra .= "RENEW|INFO)\n";
+ if ($debugOption == '-D') {
+ $dhcp6cscriptwithoutra .= "/usr/bin/logger -t dhcp6c \"dhcp6c renew, no change - bypassing update on {$wanif}\"\n";
+ }
+ $dhcp6cscriptwithoutra .= "esac\n";
if (!@file_put_contents(
"{$g['varetc_path']}/dhcp6c_{$interface}_dhcp6withoutra_script.sh",
$dhcp6cscriptwithoutra)) {
@@ -4048,6 +4120,7 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
unset($dhcp6cscriptwithoutra);
return 1;
}
+
unset($dhcp6cscriptwithoutra);
@chmod(
"{$g['varetc_path']}/dhcp6c_{$interface}_dhcp6withoutra_script.sh",
@@ -4062,12 +4135,41 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
if (!isset($wancfg['dhcp6withoutra'])) {
$dhcp6cscript .= "dmips=\${new_domain_name_servers}\n";
$dhcp6cscript .= "dmnames=\${new_domain_name}\n";
+ $dhcp6cscript .= "case \$REASON in\n";
+ $dhcp6cscript .= "REQUEST)\n";
+ $dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
+ if ($debugOption == '-D') {
+ $dhcp6cscript .= "/usr/bin/logger -t dhcp6c \"dhcp6c REQUEST on {$wanif} - running rc.newwanipv6\"\n";
+ }
+ $dhcp6cscript .= ";;\n";
+ $dhcp6cscript .= "REBIND)\n";
+ if ($debugOption == '-D') {
+ $dhcp6cscript .= "/usr/bin/logger -t dhcp6c \"dhcp6c rebind on {$wanif}\"\n";
+ }
+ $dhcp6cscript .= ";;\n";
+ if (isset($wancfg['dhcp6norelease'])) {
+ $dhcp6cscript .= "EXIT)\n";
+ } else {
+ $dhcp6cscript .= "RELEASE)\n";
+ }
+ if ($debugOption == '-D') {
+ $dhcp6cscript .= "/usr/bin/logger -t dhcp6c \"dhcp6c EXIT or RELEASE on {$wanif} running rc.newwanipv6\"\n";
+ }
+ $dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
+ $dhcp6cscript .= ";;\n";
+ $dhcp6cscript .= "RENEW|INFO)\n";
+ if ($debugOption == '-D') {
+ $dhcp6cscript .= "/usr/bin/logger -t dhcp6c \"dhcp6c renew, no change - bypassing update on {$wanif}\"\n";
+ }
+ $dhcp6cscript .= "esac\n";
} else {
// Need to get the paramaters from the dhcp6cwithoutRA run
$dhcp6cscript .= "dmips=\$(cat \"/tmp/{$wanif}_domain_name_servers\")\n";
$dhcp6cscript .= "dmnames=\$(cat \"/tmp/{$wanif}_new_domain_name\")\n";
+ $dhcp6cscript .= "/bin/sleep 1\n";
+ $dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
}
- $dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
+
/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
@@ -4077,9 +4179,6 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
unset($dhcp6cscript);
@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
- $debugOption = isset($wancfg['dhcp6debug']) ? "-D" : "-d";
- $noreleaseOption = isset($wancfg['dhcp6norelease']) ? "-n" : "";
-
$rtsoldscript = "#!/bin/sh\n";
$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
@@ -4097,16 +4196,16 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
* of dhcp6c being launched
*/
$rtsoldscript .= "if [ ! -f /tmp/dhcp6c_{$wanif}_lock ]; then\n";
- $rtsoldscript .= "\tif [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
- $rtsoldscript .= "\t\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
- $rtsoldscript .= "\t\t/bin/rm -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
- $rtsoldscript .= "\t\t/bin/sleep 1\n";
- $rtsoldscript .= "\tfi\n";
/*
* Create the lock file, trying to prevent multiple instances
* of dhcp6c being launched
*/
$rtsoldscript .= "\t/usr/bin/touch /tmp/dhcp6c_{$wanif}_lock\n";
+ $rtsoldscript .= "\tif [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
+ $rtsoldscript .= "\t\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
+ $rtsoldscript .= "\t\t/bin/rm -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
+ $rtsoldscript .= "\t\t/bin/sleep 1\n";
+ $rtsoldscript .= "\tfi\n";
$rtsoldscript .= "\t/usr/local/sbin/dhcp6c {$debugOption} " .
"{$noreleaseOption} -c {$g['varetc_path']}/dhcp6c_{$interface}.conf " .
"-p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
@@ -4132,10 +4231,6 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) {
unset($rtsoldscript);
@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
- /* accept router advertisements for this interface */
- log_error("Accept router advertisements on interface {$wanif} ");
- mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
-
if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
sleep(2);
OpenPOWER on IntegriCloud