diff options
author | Renato Botelho <renato@netgate.com> | 2017-01-26 09:35:15 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2017-01-26 09:35:15 -0200 |
commit | 7ae710d4447d0ccd5cdc1d8040135642623eea14 (patch) | |
tree | adfe5d754daf4e44b120a604b3848944a4c44b4f /src/etc/inc/interfaces.inc | |
parent | 6a9873428dd40ab55151f7b3355b078726684f67 (diff) | |
parent | ce66d4a4e5aa2f68cf46f9de9625e72dc495f1d3 (diff) | |
download | pfsense-7ae710d4447d0ccd5cdc1d8040135642623eea14.zip pfsense-7ae710d4447d0ccd5cdc1d8040135642623eea14.tar.gz |
Merge pull request #3410 from marjohn56/RTSOLD-lock-creation,-dhcp6c-launch-&-kill-changes-#3
Diffstat (limited to 'src/etc/inc/interfaces.inc')
-rw-r--r-- | src/etc/inc/interfaces.inc | 122 |
1 files changed, 97 insertions, 25 deletions
diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 43af567..5d4ba8e 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); + kill_dhcp6client_process($realif,isset($ifcfg['dhcp6norelease'])); 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,14 +3039,44 @@ function find_dhcp6c_process($interface) { return intval($pid); } -function kill_dhcp6client_process($interface) { +function kill_dhcp6client_process($interface,$norelease) { + global $g; + if (empty($interface) || !does_interface_exist($interface)) { return; } if (($pid = find_dhcp6c_process($interface)) != 0) { - mwexec("kill -9 {$pid}"); - sleep(1); + /* 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 */ + // Debug - next line remove if not required + log_error("shutting down dhcp6c process"); + $sig = (isset($norelease) ? SIGKILL : SIGTERM); + posix_kill($pid,$sig); + if(!isset($norelease)) { + sleep(2); //Allow dhcp6c to send releae and exit gracefully if needed. + } + } + /* Clear the RTSOLD script created lock & tidy up */ + unlink_if_exists("/tmp/dhcp6c_{$interface}_lock"); + unlink_if_exists("{$g['varrun_path']}/dhcp6c_{$interface}.pid"); // just in case! +} + +function run_dhcp6client_process($interface, $wancfg) { + global $g; + + $debugOption = isset($wancfg['dhcp6debug']) ? "-D" : "-d"; + $noreleaseOption = isset($wancfg['dhcp6norelease']) ? "-n" : ""; + // Only run this if the lock does not exist. In theory the lock being there in this mode means the user has selected dhcp6withoutRA while a session is active in the other mode + // It should not happen as the process should have been killed and the lock deleted. + if(!file_exists("/tmp/dhcp6c_{$interface}_lock")) { + + kill_dhcp6client_process($interface,isset($wancfg['dhcp6norelease'])); //Should not be required, but belts an + + touch("/tmp/dhcp6c_{$interface}_lock"); // Lock it, only one run please. + mwexec("/usr/local/sbin/dhcp6c {$debugOption} {$noreleaseOption} -c {$g['varetc_path']}/dhcp6c_wan.conf -p {$g['varrun_path']}/dhcp6c_{$interface}.pid {$interface}"); + log_error(sprintf(gettext("Starting dhcp6 client for interface wan %s in DHCP6 without RA mode"), $wanif)); } } @@ -3892,7 +3922,7 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) { log_error(gettext("Failed to write user DUID file!")); } } - + if ($wancfg['adv_dhcp6_config_file_override']) { // DHCP6 Config File Override $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); @@ -3929,7 +3959,13 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) { $dhcp6cconf .= "\trequest domain-name-servers;\n"; $dhcp6cconf .= "\trequest domain-name;\n"; + + /* dhcp6c will run different scripts depending on whether dhcpwithoutra is set or unset. */ + if (isset($wancfg['dhcp6withoutra'])) { + $dhcp6cconf .= "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_dhcp6withoutra_script.sh\"; # we'd like nameservers and RTSOLD to do all the work\n"; + } else { $dhcp6cconf .= "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n"; + } $dhcp6cconf .= "};\n"; if (!isset($wancfg['dhcp6prefixonly'])) { @@ -3968,10 +4004,37 @@ 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"; + $dhcp6cscriptwithoutra .= "# This shell script launches rtsold.\n"; + $dhcp6cscriptwithoutra .= "dmips=\${new_domain_name_servers}\n"; + $dhcp6cscriptwithoutra .= "dmnames=\${new_domain_name}\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 .= "/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}\n"; + + if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_dhcp6withoutra_script.sh", $dhcp6cscriptwithoutra)) { + printf("Error: cannot open dhcp6c_{$interface}_dhcp6cwithoutra_script.sh in interface_dhcpv6_configure() for writing.\n"); + unset($dhcp6cscriptwithoutra); + return 1; + } + unset($dhcp6cscriptwithoutra); + @chmod("{$g['varetc_path']}/dhcp6c_{$interface}_dhcp6withoutra_script.sh", 0755); + + /* Dual mode wan_dhcp6c script with variations depending on node */ + /* dhcp6 will run the wan ipv6 configure */ $dhcp6cscript = "#!/bin/sh\n"; $dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n"; - $dhcp6cscript .= "dmips=\${new_domain_name_servers}\n"; - $dhcp6cscript .= "dmnames=\${new_domain_name}\n"; + if (!isset($wancfg['dhcp6withoutra'])) { + $dhcp6cscript .= "dmips=\${new_domain_name_servers}\n"; + $dhcp6cscript .= "dmnames=\${new_domain_name}\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 .= "/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)) { @@ -3982,6 +4045,9 @@ 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"; @@ -3990,22 +4056,25 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) { /* non ipoe Process */ if (!isset($wancfg['dhcp6withoutra'])) { + // We only want this script to run once, and if it runs twice then do not launch dhcp6c again, this only happens if dhcpwithoutra is not set + // Check for a lock file, trying to prevent multiple instances of dhcp6c being launched + $rtsoldscript .= "if [ ! -f /tmp/dhcp6c_{$wanif}_lock ]; then\n"; $rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n"; $rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n"; + $rtsoldscript .= "\t/bin/rm -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n"; $rtsoldscript .= "\t/bin/sleep 1\n"; $rtsoldscript .= "fi\n"; - } else { - $rtsoldscript .= "{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\n"; - $rtsoldscript .= "/bin/sleep 1\n"; - } - $debugOption = isset($wancfg['dhcp6debug']) ? "-D" : "-d"; - $noreleaseOption = isset($wancfg['dhcp6norelease']) ? "-n" : ""; - - - /* add the start of dhcp6c to the rtsold script if we are going to wait for ra */ - if (!isset($wancfg['dhcp6withoutra'])) { + // Create the lock file, trying to prevent multiple instances of dhcp6c being launched + $rtsoldscript .= "/usr/bin/touch /tmp/dhcp6c_{$wanif}_lock\n"; $rtsoldscript .= "/usr/local/sbin/dhcp6c {$debugOption} {$noreleaseOption} -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n"; $rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n"; + // else statement is really just debugger info and can be removed if not required. + $rtsoldscript .= "else\n"; + $rtsoldscript .= "/usr/bin/logger -t rtsold \"RTSOLD Lock in place\"\n"; + $rtsoldscript .= "fi\n"; + } else { + $rtsoldscript .= "{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\n"; // The script needs to run in dhcp6withoutra mode as RA may not have been received, or there can be a delay with certain ISPs + $rtsoldscript .= "/bin/sleep 1\n"; } /* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */ if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) { @@ -4020,21 +4089,24 @@ function interface_dhcpv6_configure($interface = "wan", $wancfg) { log_error("Accept router advertisements on interface {$wanif} "); mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv"); - /* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */ if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) { killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid"); sleep(2); } - /* start dhcp6c here if we don't want to wait for ra */ if (isset($wancfg['dhcp6withoutra'])) { - kill_dhcp6client_process($wanif); - - mwexec("/usr/local/sbin/dhcp6c {$debugOption} {$noreleaseOption} -c {$g['varetc_path']}/dhcp6c_wan.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}"); - mwexec("/usr/bin/logger -t info 'Starting dhcp6 client for interface wan({$wanif} in DHCP6 without RA mode)'"); + /* start dhcp6c here if we don't want to wait for ra - calls seperate function */ + // In this mode dhcp6c launches rtsold via its script. RTSOLD will then run the configure on receipt of the RA. + if(!file_exists("/tmp/dhcp6c_{$wanif}_lock")) // Already started. interface_dhcpv6_configure() appears to get called multiple times. Taking the interface down or releasing will kill the client. + { + // If the interface is being brought up, wait for the interface to configure accept RA before launching. Otherwise it is not ready to accept and will fail. + sleep(3); + run_dhcp6client_process($wanif,$wancfg); + } + } else { + /* fire up rtsold for IPv6 RAs, this backgrounds immediately ( it does not background, it exits! ) It will launch dhcp6c if dhcpwihtoutra is not set*/ + mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}"); } - mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}"); - /* NOTE: will be called from rtsold invoked script * link_interface_to_track6($interface, "update"); */ |