mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 16:14:40 +00:00
system: rewrite the default route handling
With this, there is consistency in setting the default route and associated marker file. Nothing is done before the decision is final, so we may not end up with a missing route after an attempt to reconfigure for something that doesn't work anyway. DHCPv4 and PPP still do this manually, but we will have to route them through the same logic instead of them manually handling their routes. 6rd and 6to4 may have a similar issue as well. While here, swap the system_routing_configure() arguments to align with the way other configure functions present their arguments (verbose print flag first). Gateway monitoring and default switching improvement since 2016. Push $keep into default handling, it may be useful in general to avoid spurious switches. It could also be a default probably.
This commit is contained in:
parent
9ca61d8b3e
commit
09f45fbdbf
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Copyright (C) 2016-2018 Franco Fichtner <franco@opnsense.org>
|
||||
Copyright (C) 2008 Bill Marquette <bill.marquette@gmail.com>
|
||||
Copyright (C) 2008 Seth Mos <seth.mos@dds.nl>
|
||||
Copyright (C) 2010 Ermal Luçi
|
||||
@ -769,25 +770,8 @@ function fixup_default_gateway($gateways_status, $gateways_arr)
|
||||
continue;
|
||||
}
|
||||
|
||||
$defaultif = get_real_interface($gateways_arr[$dfltgwname]['friendlyiface']);
|
||||
$gwipmatch = $dfltgwip;
|
||||
if (is_linklocal($dfltgwip)) {
|
||||
/* correct match in IPv6 case */
|
||||
$gwipmatch .= "%{$defaultif}";
|
||||
}
|
||||
|
||||
$tmpcmd = "/sbin/route -n get -{$ipprotocol} default 2>/dev/null | /usr/bin/awk '/gateway:/ {print $2}'";
|
||||
$defaultgw = trim(exec($tmpcmd), " \n");
|
||||
if ($defaultgw != $gwipmatch) {
|
||||
foreach (glob('/tmp/*_defaultgw' . ($ipprotocol == 'inet' ? '' : 'v6')) as $to_delete) {
|
||||
log_error("GATEWAYS: removing {$to_delete}");
|
||||
@unlink($to_delete);
|
||||
}
|
||||
log_error("Switching default gateway to $dfltgwname ($dfltgwip on $defaultif)");
|
||||
@file_put_contents("/tmp/{$defaultif}_defaultgw" . ($ipprotocol == 'inet' ? '' : 'v6'), $dfltgwip);
|
||||
/* XXX fargw and IPv6 should be cleaned up to make it easier to read */
|
||||
system_default_route($dfltgwip, !isset($gateways_arr[$dfltgwname]['fargw']) && $ipprotocol == 'inet' ? null : $defaultif);
|
||||
}
|
||||
/* switch only if another gateway is set aa the default */
|
||||
system_default_route($dfltgwip, $ipprotocol, $gateways_arr[$dfltgwname]['friendlyiface'], isset($gateways_arr[$dfltgwname]['fargw']), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -995,7 +995,7 @@ function interface_gif_configure(&$gif, $gifkey = "")
|
||||
foreach ($iflist as $ifname) {
|
||||
if ($config['interfaces'][$ifname]['if'] == $gifif) {
|
||||
if (get_interface_gateway($ifname) || get_interface_gateway_v6($ifname)) {
|
||||
system_routing_configure($ifname);
|
||||
system_routing_configure(false, $ifname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1076,7 +1076,7 @@ function interfaces_configure($verbose = false)
|
||||
interfaces_group_setup();
|
||||
|
||||
if ($reload) {
|
||||
system_routing_configure('', $verbose);
|
||||
system_routing_configure($verbose);
|
||||
ipsec_configure_do($verbose);
|
||||
plugins_configure('dns', $verbose);
|
||||
services_dhcpd_configure('all', array(), $verbose);
|
||||
@ -2713,7 +2713,7 @@ function interface_configure($interface = 'wan', $reloadall = false, $linkupeven
|
||||
}
|
||||
|
||||
if ($reloadall == true) {
|
||||
system_routing_configure($interface);
|
||||
system_routing_configure(false, $interface);
|
||||
ipsec_configure_do();
|
||||
plugins_configure('dns');
|
||||
services_dhcpd_configure();
|
||||
|
||||
@ -417,30 +417,67 @@ function system_host_route($host, $gateway, $delete = true, $add = true)
|
||||
}
|
||||
}
|
||||
|
||||
function system_default_route($gateway, $interface = null)
|
||||
function system_default_route($gateway, $family, $interface, $far = false, $keep = false)
|
||||
{
|
||||
if (is_ipaddrv4($gateway)) {
|
||||
$family = 'inet';
|
||||
} elseif (is_ipaddrv6($gateway)) {
|
||||
$family = 'inet6';
|
||||
if (is_linklocal($gateway)) {
|
||||
$gateway .= "%{$interface}";
|
||||
$realif = get_real_interface($interface);
|
||||
|
||||
switch ($family) {
|
||||
case 'inet':
|
||||
break;
|
||||
case 'inet6':
|
||||
if (is_linklocal($gateway)) {
|
||||
$gateway .= "%{$realif}";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error("ROUTING: unknown address family '{$family}'");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($keep) {
|
||||
$tmpcmd = "/sbin/route -n get -{$family} default 2>/dev/null | /usr/bin/awk '/gateway:/ {print $2}'";
|
||||
$current = trim(exec($tmpcmd), " \n");
|
||||
if ($current == $gateway) {
|
||||
log_error("ROUTING: keeping current default gateway '{$gateway}'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($family == 'inet') {
|
||||
foreach (glob('/tmp/*_defaultgw', GLOB_BRACE) as $to_delete) {
|
||||
log_error("ROUTING: removing {$to_delete}");
|
||||
@unlink($to_delete);
|
||||
}
|
||||
|
||||
log_error("ROUTING: creating /tmp/{$realif}_defaultgw using '{$gateway}'");
|
||||
@file_put_contents("/tmp/{$realif}_defaultgw", $gateway);
|
||||
|
||||
if (!$far) {
|
||||
$realif = null;
|
||||
}
|
||||
/* IPv6 does not support far gateway notion */
|
||||
$interface = null;
|
||||
} else {
|
||||
return;
|
||||
foreach (glob('/tmp/*_defaultgwv6', GLOB_BRACE) as $to_delete) {
|
||||
log_error("ROUTING: removing {$to_delete}");
|
||||
@unlink($to_delete);
|
||||
}
|
||||
|
||||
log_error("ROUTING: creating /tmp/{$realif}_defaultgwv6 using '{$gateway}'");
|
||||
@file_put_contents("/tmp/{$realif}_defaultgwv6", $gateway);
|
||||
|
||||
/* IPv6 does not support far gateway notion */
|
||||
$realif = null;
|
||||
$far = false;
|
||||
}
|
||||
|
||||
mwexecf('/sbin/route delete -%s default', array($family), true);
|
||||
if (!empty($interface)) {
|
||||
mwexecf('/sbin/route delete -%s %s -interface %s', array($family, $gateway, $interface), true);
|
||||
mwexecf('/sbin/route add -%s %s -interface %s', array($family, $gateway, $interface));
|
||||
if (!empty($realif)) {
|
||||
mwexecf('/sbin/route delete -%s %s -interface %s', array($family, $gateway, $realif), true);
|
||||
mwexecf('/sbin/route add -%s %s -interface %s', array($family, $gateway, $realif));
|
||||
}
|
||||
mwexecf('/sbin/route add -%s default %s', array($family, $gateway));
|
||||
}
|
||||
|
||||
function system_routing_configure($interface = '', $verbose = false)
|
||||
function system_routing_configure($verbose = false, $interface = '')
|
||||
{
|
||||
global $config;
|
||||
|
||||
@ -449,58 +486,45 @@ function system_routing_configure($interface = '', $verbose = false)
|
||||
flush();
|
||||
}
|
||||
|
||||
$gatewayip = "";
|
||||
$interfacegw = "";
|
||||
$interfacegw = '';
|
||||
$foundgw = false;
|
||||
$gatewayipv6 = "";
|
||||
$interfacegwv6 = "";
|
||||
$foundgwv6 = false;
|
||||
$gatewayip = '';
|
||||
$fargw = false;
|
||||
|
||||
$interfacegwv6 = '';
|
||||
$foundgwv6 = false;
|
||||
$gatewayipv6 = '';
|
||||
|
||||
if (!empty($interface)) {
|
||||
log_error("ROUTING: entering configure using '${interface}'");
|
||||
} else {
|
||||
log_error("ROUTING: entering configure using defaults");
|
||||
}
|
||||
|
||||
/* tack on all the hard defined gateways as well */
|
||||
if (isset($config['gateways']['gateway_item'])) {
|
||||
foreach (glob('/tmp/*_defaultgw{,v6}', GLOB_BRACE) as $to_delete) {
|
||||
log_error("ROUTING: removing {$to_delete}");
|
||||
@unlink($to_delete);
|
||||
}
|
||||
|
||||
foreach ($config['gateways']['gateway_item'] as $gateway) {
|
||||
if (isset($gateway['defaultgw'])) {
|
||||
if ($foundgw == false && $gateway['ipprotocol'] != "inet6" && (is_ipaddrv4($gateway['gateway']) || $gateway['gateway'] == "dynamic")) {
|
||||
if ($gateway['gateway'] == "dynamic") {
|
||||
if ($foundgw == false && $gateway['ipprotocol'] != 'inet6') {
|
||||
if ($gateway['gateway'] == 'dynamic') {
|
||||
$gateway['gateway'] = get_interface_gateway($gateway['interface']);
|
||||
}
|
||||
|
||||
$interfacegw = $gateway['interface'];
|
||||
$fargw = isset($gateway['fargw']);
|
||||
$gatewayip = $gateway['gateway'];
|
||||
$interfacegw = $gateway['interface'];
|
||||
if (!empty($gateway['interface'])) {
|
||||
$defaultif = get_real_interface($gateway['interface']);
|
||||
if ($defaultif && is_ipaddrv4($gatewayip)) {
|
||||
log_error("ROUTING: creating /tmp/{$defaultif}_defaultgw");
|
||||
@file_put_contents("/tmp/{$defaultif}_defaultgw", $gatewayip);
|
||||
}
|
||||
}
|
||||
$foundgw = true;
|
||||
} elseif ($foundgwv6 == false && $gateway['ipprotocol'] == "inet6" && (is_ipaddrv6($gateway['gateway']) || $gateway['gateway'] == "dynamic")) {
|
||||
if ($gateway['gateway'] == "dynamic") {
|
||||
|
||||
log_error("ROUTING: IPv4 default gateway set to {$interfacegw}");
|
||||
} elseif ($foundgwv6 == false && $gateway['ipprotocol'] == 'inet6') {
|
||||
if ($gateway['gateway'] == 'dynamic') {
|
||||
$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
|
||||
}
|
||||
$gatewayipv6 = $gateway['gateway'];
|
||||
|
||||
$interfacegwv6 = $gateway['interface'];
|
||||
if (!empty($gateway['interface'])) {
|
||||
$defaultifv6 = get_real_interface($gateway['interface']);
|
||||
if ($defaultifv6 && is_ipaddrv6($gatewayipv6)) {
|
||||
log_error("ROUTING: creating /tmp/{$defaultifv6}_defaultgwv6");
|
||||
@file_put_contents("/tmp/{$defaultifv6}_defaultgwv6", $gatewayipv6);
|
||||
}
|
||||
}
|
||||
$gatewayipv6 = $gateway['gateway'];
|
||||
$foundgwv6 = true;
|
||||
|
||||
log_error("ROUTING: IPv6 default gateway set to {$interfacegwv6}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,43 +540,34 @@ function system_routing_configure($interface = '', $verbose = false)
|
||||
* In fact the following code is a mini gateway switcher
|
||||
* facility which can only switch one hardcoded gateway and
|
||||
* may obscure a problem with the setup for a long time... :(
|
||||
*
|
||||
* XXX Find a way to infer an upstream-capable interface or
|
||||
* maybe make gateway switching the hardcoded behaviour, or
|
||||
* at least the new default.
|
||||
*/
|
||||
|
||||
if (!$foundgw) {
|
||||
$interfacegw = 'wan';
|
||||
$defaultif = get_real_interface($interfacegw);
|
||||
log_error("ROUTING: no IPv4 default gateway set, assuming {$interfacegw}");
|
||||
$gatewayip = get_interface_gateway($interfacegw);
|
||||
if (is_ipaddrv4($gatewayip)) {
|
||||
log_error("ROUTING: no IPv4 default gateway set, assuming {$interfacegw} on '{$defaultif}' ({$gatewayip})");
|
||||
@file_put_contents("/tmp/{$defaultif}_defaultgw", $gatewayip);
|
||||
} else {
|
||||
log_error("ROUTING: no IPv4 default gateway set, skipping {$interfacegw} on '{$defaultif}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$foundgwv6) {
|
||||
$interfacegwv6 = 'wan';
|
||||
$defaultifv6 = get_real_interface($interfacegwv6);
|
||||
log_error("ROUTING: no IPv6 default gateway set, assuming {$interfacegwv6}");
|
||||
$gatewayipv6 = get_interface_gateway_v6($interfacegwv6);
|
||||
if (is_ipaddrv6($gatewayipv6)) {
|
||||
log_error("ROUTING: no IPv6 default gateway set, trying {$interfacegwv6} on '{$defaultifv6}' ({$gatewayipv6})");
|
||||
@file_put_contents("/tmp/{$defaultifv6}_defaultgwv6", $gatewayipv6);
|
||||
} else {
|
||||
log_error("ROUTING: no IPv6 default gateway set, skipping {$interfacegwv6} on '{$defaultifv6}'");
|
||||
$interfacegwv6 = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ((empty($interface) || $interface == $interfacegw) && is_ipaddrv4($gatewayip)) {
|
||||
log_error("ROUTING: setting IPv4 default route to {$gatewayip}");
|
||||
system_default_route($gatewayip, $fargw ? $defaultif : null);
|
||||
system_default_route($gatewayip, 'inet', $interfacegw, $fargw);
|
||||
} else {
|
||||
log_error("ROUTING: skipping IPv4 default route");
|
||||
}
|
||||
|
||||
if ((empty($interface) || $interface == $interfacegwv6) && is_ipaddrv6($gatewayipv6)) {
|
||||
log_error("ROUTING: setting IPv6 default route to {$gatewayipv6}");
|
||||
system_default_route($gatewayipv6, $defaultifv6);
|
||||
system_default_route($gatewayipv6, 'inet6', $interfacegwv6, false);
|
||||
} else {
|
||||
log_error("ROUTING: skipping IPv6 default route");
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ filter_pflog_start(true);
|
||||
setup_gateways_monitor(true);
|
||||
plugins_configure('earlybootup', true);
|
||||
system_cron_configure(true, true);
|
||||
system_routing_configure('', true);
|
||||
system_routing_configure(true);
|
||||
|
||||
plugins_configure('dns', true);
|
||||
services_dhcpd_configure('all', array(), true);
|
||||
|
||||
@ -144,7 +144,7 @@ if (isset($config['gifs']['gif']) && is_array($config['gifs']['gif'])){
|
||||
if (!empty($confif)) {
|
||||
interface_configure($confif);
|
||||
}
|
||||
system_routing_configure($ifname);
|
||||
system_routing_configure(false, $ifname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,7 +161,7 @@ $cacheip = @file_get_contents($cacheip_file);
|
||||
if (!is_ipaddr($cacheip) || $ip != $cacheip || !is_ipaddr($configip)) {
|
||||
@unlink($cacheip_file);
|
||||
|
||||
system_routing_configure($interface);
|
||||
system_routing_configure(false, $interface);
|
||||
setup_gateways_monitor();
|
||||
plugins_configure('vpn', false, array($interface));
|
||||
filter_configure_sync();
|
||||
|
||||
@ -142,7 +142,7 @@ if (!is_ipaddr($cacheip) || $ip != $cacheip || !is_ipaddr($configip)) {
|
||||
|
||||
@unlink($cacheip_file);
|
||||
|
||||
system_routing_configure($interface);
|
||||
system_routing_configure(false, $interface);
|
||||
setup_gateways_monitor();
|
||||
plugins_configure('vpn', false, array($interface));
|
||||
filter_configure_sync();
|
||||
|
||||
@ -42,6 +42,6 @@ foreach (glob("/tmp/delete_route_*.todo") as $filename) {
|
||||
unlink($filename);
|
||||
}
|
||||
|
||||
system_routing_configure('', true);
|
||||
system_routing_configure(true);
|
||||
setup_gateways_monitor(true);
|
||||
filter_configure_sync(true);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user