From 94bd7fb3a52e375dcd25c416e36389f96060a8fd Mon Sep 17 00:00:00 2001 From: Renato Botelho Date: Tue, 18 Oct 2016 11:01:47 -0200 Subject: [PATCH] Fix #6828 Until 2.3.x pfSense carried a patch that changed the behavior of 'route change' command, making it add the route when it fails to change. On 2.4 this patch was removed and will not be added back. This change adjust PHP code to deal with route add / change and make it work without the patch --- src/etc/inc/gwlb.inc | 18 +++++++-------- src/etc/inc/interfaces.inc | 8 +++---- src/etc/inc/system.inc | 41 +++++++++++---------------------- src/etc/inc/util.inc | 30 ++++++++++++++++++++++++ src/etc/inc/vpn.inc | 4 ++-- src/usr/local/sbin/ppp-linkup | 12 ++++++---- src/usr/local/sbin/prefixes.php | 3 ++- 7 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/etc/inc/gwlb.inc b/src/etc/inc/gwlb.inc index e31092aa86..6a5378e57d 100644 --- a/src/etc/inc/gwlb.inc +++ b/src/etc/inc/gwlb.inc @@ -223,12 +223,11 @@ function setup_gateways_monitor() { */ if (is_ipaddrv4($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) { log_error(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $gateway['gateway'])); + $route_to = "-host {$gateway['monitor']}"; if (interface_isppp_type($gateway['friendlyiface'])) { - mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) . - " -iface " . escapeshellarg($gateway['interface']), true); + route_add_or_change("{$route_to} -iface {$gateway['interface']}"); } else { - mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) . - " " . escapeshellarg($gateway['gateway']), true); + route_add_or_change("{$route_to} {$gateway['gateway']}"); } pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp"); @@ -265,12 +264,11 @@ function setup_gateways_monitor() { */ if ($gateway['gateway'] != $gateway['monitor']) { log_error(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $gateway['gateway'])); + $route_to = "-host -inet6 {$gateway['monitor']}"; if (interface_isppp_type($gateway['friendlyiface'])) { - mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) . - " -iface " . escapeshellarg($gateway['interface']), true); + route_add_or_change("{$route_to} -iface {$gateway['interface']}"); } else { - mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) . - " " . escapeshellarg($gateway['gateway']), true); + route_add_or_change("{$route_to} {$gateway['gateway']}"); } pfSense_kill_states("::0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmpv6"); @@ -842,7 +840,7 @@ function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) { } else { $inetfamily = "-inet"; } - mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}"); + route_add_or_change("{$inetfamily} default {$gateways_arr[$upgw]['gateway']}"); } } else if (!empty($dfltgwname)) { $defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n"); @@ -861,7 +859,7 @@ function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) { } } if ($defaultgw != $gateways_arr[$dfltgwname]['gateway']) { - mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}"); + route_add_or_change("-{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}"); } } } diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 2ae27876b1..1e0be5d20e 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -1006,10 +1006,10 @@ function interface_gif_configure(&$gif, $gifkey = "") { } if (is_ipaddrv4($realifgw)) { - mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}"); + route_add_or_change("-host {$gif['remote-addr']} {$realifgw}"); } if (is_ipaddrv6($realifgw)) { - mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}"); + route_add_or_change("-host -inet6 {$gif['remote-addr']} {$realifgw}"); } interfaces_bring_up($gifif); @@ -3738,7 +3738,7 @@ function interface_6rd_configure($interface = "wan", $wancfg) { $ip4gateway = get_interface_gateway($interface); if (is_ipaddrv4($ip4gateway)) { - mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}"); + route_add_or_change("-host {$wancfg['gateway-6rd']} {$ip4gateway}"); } /* configure dependent interfaces */ @@ -3845,7 +3845,7 @@ function interface_6to4_configure($interface = "wan", $wancfg) { $ip4gateway = get_interface_gateway($interface); if (is_ipaddrv4($ip4gateway)) { - mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}"); + route_add_or_change("-host 192.88.99.1 {$ip4gateway}"); } if (!platform_booting()) { diff --git a/src/etc/inc/system.inc b/src/etc/inc/system.inc index e9ecd968ce..8d4f406719 100644 --- a/src/etc/inc/system.inc +++ b/src/etc/inc/system.inc @@ -213,17 +213,14 @@ function system_resolvconf_generate($dynupdate = false) { $dnsserver = $syscfg['dnsserver'][$dnscounter - 1]; if (is_ipaddr($gatewayip)) { - $cmd = 'change'; + route_add_or_change("-host {$inet6}{$dnsserver} {$gatewayip}"); } else { /* Remove old route when disable gw */ - $cmd = 'delete'; - $gatewayip = ''; - } - - mwexec("/sbin/route {$cmd} -host {$inet6}{$dnsserver} {$gatewayip}"); - if (isset($config['system']['route-debug'])) { - $mt = microtime(); - log_error("ROUTING debug: $mt - route {$cmd} -host {$inet6}{$dnsserver} {$gatewayip}"); + mwexec("/sbin/route delete -host {$inet6}{$dnsserver}"); + if (isset($config['system']['route-debug'])) { + $mt = microtime(); + log_error("ROUTING debug: $mt - route delete -host {$inet6}{$dnsserver}"); + } } } } @@ -593,12 +590,8 @@ function system_routing_configure($interface = "") { $srinterfacegw = $gateway['interface']; if (is_ipaddr($srgatewayip) && !empty($srinterfacegw)) { $inet = (!is_ipaddrv4($srgatewayip) ? "-inet6" : "-inet"); - $cmd = "/sbin/route change {$inet} " . escapeshellarg($srgatewayip) . " "; - mwexec($cmd . "-iface " . escapeshellarg($srinterfacegw)); - if (isset($config['system']['route-debug'])) { - $mt = microtime(); - log_error("ROUTING debug: $mt - $cmd -iface $srinterfacegw "); - } + route_add_or_change("{$inet} {$srgatewayip} " . + "-iface {$srinterfacegw}"); } } } @@ -608,7 +601,7 @@ function system_routing_configure($interface = "") { ; } else if (is_ipaddrv4($gatewayip)) { log_error(sprintf(gettext("ROUTING: setting default route to %s"), $gatewayip)); - mwexec("/sbin/route change -inet default " . escapeshellarg($gatewayip)); + route_add_or_change("-inet default {$gatewayip}"); } if (!empty($interface) && $interface != $interfacegwv6) { @@ -619,7 +612,7 @@ function system_routing_configure($interface = "") { $ifscope = "%{$defaultifv6}"; } log_error(sprintf(gettext("ROUTING: setting IPv6 default route to %s"), $gatewayipv6 . $ifscope)); - mwexec("/sbin/route change -inet6 default " . escapeshellarg("{$gatewayipv6}{$ifscope}")); + route_add_or_change("-inet6 default {$gatewayipv6}{$ifscope}"); } } @@ -710,7 +703,7 @@ function system_staticroutes_configure($interface = "", $update_dns = false) { $inet = (is_subnetv6($ip) ? "-inet6" : "-inet"); - $cmd = "/sbin/route change {$inet} {$blackhole} " . escapeshellarg($ip) . " "; + $cmd = "{$inet} {$blackhole} {$ip} "; if (is_subnet($ip)) { if (is_ipaddr($gatewayip)) { @@ -718,17 +711,9 @@ function system_staticroutes_configure($interface = "", $update_dns = false) { // add interface scope for link local v6 routes $gatewayip .= "%$interfacegw"; } - mwexec($cmd . escapeshellarg($gatewayip)); - if (isset($config['system']['route-debug'])) { - $mt = microtime(); - log_error("ROUTING debug: $mt - $cmd $gatewayip"); - } + route_add_or_change($cmd . $gatewayip); } else if (!empty($interfacegw)) { - mwexec($cmd . "-iface " . escapeshellarg($interfacegw)); - if (isset($config['system']['route-debug'])) { - $mt = microtime(); - log_error("ROUTING debug: $mt - $cmd -iface $interfacegw "); - } + route_add_or_change($cmd . "-iface {$interfacegw}"); } } } diff --git a/src/etc/inc/util.inc b/src/etc/inc/util.inc index 1736a896fc..584b99ac71 100644 --- a/src/etc/inc/util.inc +++ b/src/etc/inc/util.inc @@ -2298,6 +2298,36 @@ function explode_assoc($delimiter, $string) { return $result; } +/* Try to change a static route, if it doesn't exist, add it */ +function route_add_or_change($args) { + global $config; + + if (empty($args)) { + return false; + } + + /* First, try to add it */ + $_gb = exec(escapeshellcmd("/sbin/route add " . $args), $output, $rc); + + if (isset($config['system']['route-debug'])) { + $mt = microtime(); + log_error("ROUTING debug: $mt - ADD RC={$rc} - $args"); + } + + if ($rc != 0) { + /* If it fails, try to change it */ + $_gb = exec(escapeshellcmd("/sbin/route change " . $args), + $output, $rc); + + if (isset($config['system']['route-debug'])) { + $mt = microtime(); + log_error("ROUTING debug: $mt - CHG RC={$rc} - $args"); + } + } + + return ($rc == 0); +} + function get_staticroutes($returnsubnetsonly = false, $returnhostnames = false) { global $config, $aliastable; diff --git a/src/etc/inc/vpn.inc b/src/etc/inc/vpn.inc index 9217cc2165..bd08234450 100644 --- a/src/etc/inc/vpn.inc +++ b/src/etc/inc/vpn.inc @@ -880,7 +880,7 @@ EOD; if (!ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}")) { if (is_ipaddrv4($gatewayip)) { // log_error("IPSEC interface is not WAN but {$ifacesuse}, adding static route for VPN endpoint {$rgip} via {$gatewayip}"); - mwexec("/sbin/route change -host {$sourcehost} {$gatewayip}", true); + route_add_or_change("-host {$sourcehost} {$gatewayip}"); } } } @@ -907,7 +907,7 @@ EOD; if (!ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}")) { if (is_ipaddrv6($gatewayip)) { // log_error("IPSEC interface is not WAN but {$ifacesuse}, adding static route for VPN endpoint {$rgip} via {$gatewayip}"); - mwexec("/sbin/route change -inet6 -host {$sourcehost} {$gatewayip}", true); + route_add_or_change("-inet6 -host {$sourcehost} {$gatewayip}"); } } } diff --git a/src/usr/local/sbin/ppp-linkup b/src/usr/local/sbin/ppp-linkup index 035de7234e..7b41e0a293 100755 --- a/src/usr/local/sbin/ppp-linkup +++ b/src/usr/local/sbin/ppp-linkup @@ -50,12 +50,14 @@ if [ "${PROTOCOL}" == "inet" ]; then if echo "${DNS1_RAW}" | grep -q dns1; then DNS1=`echo "${DNS1_RAW}" | awk '{print $2}'` echo "${DNS1}" >> /var/etc/nameserver_${IF} - route change "${DNS1}" ${REMOTE_IP} + route change "${DNS1}" ${REMOTE_IP} \ + || route add "${DNS1}" ${REMOTE_IP} fi if echo "${DNS2_RAW}" | grep -q dns2; then DNS2=`echo "${DNS2_RAW}" | awk '{print $2}'` echo "${DNS2}" >> /var/etc/nameserver_${IF} - route change "${DNS2}" ${REMOTE_IP} + route change "${DNS2}" ${REMOTE_IP} \ + || route add "${DNS2}" ${REMOTE_IP} fi pfSctl -c 'service reload dns' sleep 1 @@ -75,12 +77,14 @@ elif [ "${PROTOCOL}" == "inet6" ]; then if echo "${DNS1_RAW}" | grep -q dns1; then DNS1=`echo "${DNS1_RAW}" | awk '{print $2}'` echo "${DNS1}" >> /var/etc/nameserver_v6${IF} - route change -inet6 "${DNS1}" ${REMOTE_IP} + route change -inet6 "${DNS1}" ${REMOTE_IP} \ + || route add -inet6 "${DNS1}" ${REMOTE_IP} fi if echo "${DNS2_RAW}" | grep -q dns2; then DNS2=`echo "${DNS2_RAW}" | awk '{print $2}'` echo "${DNS2}" >> /var/etc/nameserver_v6${IF} - route change -inet6 "${DNS2}" ${REMOTE_IP} + route change -inet6 "${DNS2}" ${REMOTE_IP} \ + || route add -inet6 "${DNS2}" ${REMOTE_IP} fi pfSctl -c 'service reload dns' sleep 1 diff --git a/src/usr/local/sbin/prefixes.php b/src/usr/local/sbin/prefixes.php index 29cbbf909c..746de8694a 100644 --- a/src/usr/local/sbin/prefixes.php +++ b/src/usr/local/sbin/prefixes.php @@ -98,7 +98,8 @@ foreach ($duid_arr as $entry) { // echo "add routes\n"; if (count($routes) > 0) { foreach ($routes as $address => $prefix) { - echo "/sbin/route change -inet6 {$prefix} {$address}\n"; + echo "/sbin/route change -inet6 {$prefix} {$address} " . + "|| /sbin/route add -inet6 {$prefix} {$address}\n"; } }