diff options
-rw-r--r-- | etc/inc/gwlb.inc | 309 | ||||
-rwxr-xr-x | usr/local/sbin/ppp-linkdown | 2 | ||||
-rwxr-xr-x | usr/local/sbin/ppp-linkup | 2 |
3 files changed, 144 insertions, 169 deletions
diff --git a/etc/inc/gwlb.inc b/etc/inc/gwlb.inc index 4235145..c53d5f1 100644 --- a/etc/inc/gwlb.inc +++ b/etc/inc/gwlb.inc @@ -30,19 +30,22 @@ */ -/* add static routes for monitor IP addresse - * creates monitoring configuration file +/* + * Creates monitoring configuration file and + * adds apropriate static routes. */ function setup_gateways_monitor() { - global $config; - global $g; - $gateways_arr = return_gateways_array(); - $gateways_status = return_gateways_status(); - if (!is_array($config['gateways']['gateway_item'])) - $config['gateways']['gateway_item'] = array(); + global $config, $g; - $a_gateway_item = &$config['gateways']['gateway_item']; + $gateways_arr = return_gateways_array(); + if (!is_array($gateways_arr)) { + log_error("No gateways to monitor. Apinger will not be run."); + killbypid("{$g['varrun_path']}/apinger.pid"); + @unlink("{$g['tmp_path']}/apinger.status"); + return; + } + /* Default settings. Probably should move to globals.inc? */ $a_settings = array(); $a_settings['latencylow'] = "200"; $a_settings['latencyhigh'] = "500"; @@ -131,109 +134,87 @@ target default { #rrd file "{$g['vardb_path']}/rrd/apinger-%t.rrd" } -## Targets to probe -## Each one defined with: -## target <address> { <parameter>... } -## The parameters are those described above in the "target default" section -## plus the "description" parameter. -## the <address> should be IPv4 or IPv6 address (not hostname!) - EOD; - /* add static routes for each gateway with their monitor IP */ - if(is_array($gateways_arr)) { - $i = 2; - foreach($gateways_arr as $name => $gateway) { - $gwref = $a_gateway_item[$gateway['attribute']]; - /* for dynamic gateways without an IP address we subtitute a local one */ - if(is_ipaddr($gwref['monitor'])) { - $gateway['monitor'] = $gwref['monitor']; - } else { - if ($gateway['gateway'] == "dynamic") { - $gateway['monitor'] = "127.0.0.{$i}"; - $i++; - } - if (!is_ipaddr($gateway['monitor'])) - $gateway['monitor'] = $gateway['gateway']; - } - - if (!is_ipaddr($gateway['monitor'])) + foreach($gateways_arr as $name => $gateway) { + if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) { + if (is_ipaddr($gateway['gateway'])) + $gateway['monitor'] = $gateway['gateway']; + else /* No chance to get an ip to monitor skip target. */ continue; + } - if($gateway['monitor'] == "127.0.0.{$i}") { - $gwifip = "127.0.0.1"; - } else { - $gwifip = find_interface_ip($gateway['interface']); - } - if (!is_ipaddr($gwifip)) - continue; //Skip this target - - $apingercfg .= "target \"{$gateway['monitor']}\" {\n"; - $apingercfg .= " description \"{$gateway['name']}\"\n"; - $apingercfg .= " srcip \"{$gwifip}\"\n"; - $alarms = ""; - $override = false; - if (!empty($gwref['lowloss'])) { - $alarmscfg .= "alarm loss \"{$gateway['name']}loss\" {\n"; - $alarmscfg .= "\tpercent_low {$gwref['losslow']}\n"; - $alarmscfg .= "\tpercent_high {$gwref['losshigh']}\n"; - $alarmscfg .= "}\n"; - $alarms .= "\"{$gateway['name']}loss\""; - $override = true; - } else { - if ($override == true) - $alarms .= ","; - $alarms .= "\"loss\""; - $override = true; - } - if (!empty($gwref['latencylow'])) { - $alarmscfg .= "alarm delay \"{$gateway['name']}delay\" {\n"; - $alarmscfg .= "\tdelay_low {$gwref['latencylow']}ms\n"; - $alarmscfg .= "\tdelay_high {$gwref['latencyhigh']}ms\n"; - $alarmscfg .= "}\n"; - if ($override == true) - $alarms .= ","; - $alarms .= "\"{$gateway['name']}delay\""; - $override = true; - } else { - if ($override == true) - $alarms .= ","; - $alarms .= "\"delay\""; - $override = true; - } - if (!empty($gwref['down'])) { - $alarmscfg .= "alarm down \"{$gateway['name']}down\" {\n"; - $alarmscfg .= "\ttime {$gwref['down']}s\n"; - $alarmscfg .= "}\n"; - if ($override == true) - $alarms .= ","; - $alarms .= "\"{$gateway['name']}down\""; - $override = true; - } else { - if ($override == true) - $alarms .= ","; - $alarms .= "\"down\""; - $override = true; - } + /* Interface ip is needed since apinger will bind a socket to it. */ + $gwifip = find_interface_ip($gateway['interface']); + if (!is_ipaddr($gwifip)) + continue; //Skip this target + + $apingercfg .= "target \"{$gateway['monitor']}\" {\n"; + $apingercfg .= " description \"{$gateway['name']}\"\n"; + $apingercfg .= " srcip \"{$gwifip}\"\n"; + $alarms = ""; + $override = false; + if (!empty($gateway['lowloss'])) { + $alarmscfg .= "alarm loss \"{$gateway['name']}loss\" {\n"; + $alarmscfg .= "\tpercent_low {$gateway['losslow']}\n"; + $alarmscfg .= "\tpercent_high {$gateway['losshigh']}\n"; + $alarmscfg .= "}\n"; + $alarms .= "\"{$gateway['name']}loss\""; + $override = true; + } else { if ($override == true) - $apingercfg .= "\talarms override {$alarms};\n"; - - $apingercfg .= " rrd file \"{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd\"\n"; - $apingercfg .= "}\n"; - $apingercfg .= "\n"; - if($gateway['monitor'] == $gateway['gateway']) { - /* if the gateway is the same as the monitor we do not add a - * route as this will break the routing table */ - continue; - } else { - if ($gateway['gateway'] != "dynamic" && is_ipaddr($gateway['gateway'])) { - mwexec("/sbin/route delete -host " . escapeshellarg($gateway['monitor'])); - mwexec("/sbin/route add -host " . escapeshellarg($gateway['monitor']) . - " " . escapeshellarg($gateway['gateway'])); - log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}"); - } - } + $alarms .= ","; + $alarms .= "\"loss\""; + $override = true; + } + if (!empty($gateway['latencylow'])) { + $alarmscfg .= "alarm delay \"{$gateway['name']}delay\" {\n"; + $alarmscfg .= "\tdelay_low {$gateway['latencylow']}ms\n"; + $alarmscfg .= "\tdelay_high {$gateway['latencyhigh']}ms\n"; + $alarmscfg .= "}\n"; + if ($override == true) + $alarms .= ","; + $alarms .= "\"{$gateway['name']}delay\""; + $override = true; + } else { + if ($override == true) + $alarms .= ","; + $alarms .= "\"delay\""; + $override = true; + } + if (!empty($gateway['down'])) { + $alarmscfg .= "alarm down \"{$gateway['name']}down\" {\n"; + $alarmscfg .= "\ttime {$gateway['down']}s\n"; + $alarmscfg .= "}\n"; + if ($override == true) + $alarms .= ","; + $alarms .= "\"{$gateway['name']}down\""; + $override = true; + } else { + if ($override == true) + $alarms .= ","; + $alarms .= "\"down\""; + $override = true; } + if ($override == true) + $apingercfg .= "\talarms override {$alarms};\n"; + + $apingercfg .= " rrd file \"{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd\"\n"; + $apingercfg .= "}\n"; + $apingercfg .= "\n"; + /* + * If the gateway is the same as the monitor we do not add a + * route as this will break the routing table. + * Add static routes for each gateway with their monitor IP + * not strictly necessary but is a added level of protection. + */ + if (is_ipaddr($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) { + log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}"); + mwexec("/sbin/route delete -host " . escapeshellarg($gateway['monitor']), true); + mwexec("/sbin/route add -host " . escapeshellarg($gateway['monitor']) . + " " . escapeshellarg($gateway['gateway'])); + } + $apingerconfig .= $alarmscfg; $apingerconfig .= $apingercfg; } @@ -256,7 +237,7 @@ EOD; } /* return the status of the apinger targets as a array */ -function return_gateways_status() { +function return_gateways_status($byname = false) { global $config, $g; $apingerstatus = array(); @@ -267,7 +248,11 @@ function return_gateways_status() { $status = array(); foreach($apingerstatus as $line) { $info = explode("|", $line); - $target = $info[0]; + if ($byname == false) + $target = $info[0]; + else + $target = $info[2]; + $status[$target]['monitorip'] = $info[0]; $status[$target]['srcip'] = $info[1]; $status[$target]['name'] = $info[2]; $status[$target]['lastcheck'] = $info[5] ? date('r', $info[5]) : date('r'); @@ -292,34 +277,35 @@ function return_gateways_array($disabled = false) { } $i = 0; - /* tack on all the hard defined gateways as well */ + /* Process/add all the configured gateways. */ if(is_array($config['gateways']['gateway_item'])) { foreach($config['gateways']['gateway_item'] as $gateway) { if($gateway['gateway'] == "dynamic") { $gateway['gateway'] = get_interface_gateway($gateway['interface']); /* no IP address found, set to dynamic */ - if(! is_ipaddr($gateway['gateway'])) { + if(! is_ipaddr($gateway['gateway'])) $gateway['gateway'] = "dynamic"; - } + $gateway['dynamic'] = true; } - if($gateway['monitor'] == "") { + if(empty($gateway['monitor'])) $gateway['monitor'] = $gateway['gateway']; - } - /* include the gateway index as the attribute */ + $gateway['friendlyiface'] = $gateway['interface']; - $gateway['interface'] = convert_friendly_interface_to_real_interface_name($gateway['interface']); - $gateway['attribute'] = "$i"; + $gateway['interface'] = get_real_interface($gateway['interface']); + /* include the gateway index as the attribute */ + $gateway['attribute'] = $i; $gateways_arr[$gateway['name']] = $gateway; $i++; } } + /* Process/add dynamic gateways. */ foreach($iflist as $ifname => $friendly ) { - if(! interface_has_gateway($ifname)) { + if(! interface_has_gateway($ifname)) continue; - } + $gateway = array(); $gateway['dynamic'] = false; $gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']); @@ -329,9 +315,8 @@ function return_gateways_array($disabled = false) { $gateway['attribute'] = "system"; /* Loopback dummy for dynamic interfaces without a IP */ - if(!is_ipaddr(trim($gateway['gateway'])) && $gateway['dynamic'] == true) { + if(!is_ipaddr($gateway['gateway']) && $gateway['dynamic'] == true) $gateway['gateway'] = "dynamic"; - } /* automatically skip known static and dynamic gateways we have a array entry for */ foreach($gateways_arr as $gateway_item) { @@ -352,21 +337,20 @@ function return_gateways_array($disabled = false) { } $gateway['descr'] = "Interface $ifname Dynamic Gateway"; $gateways_arr[$ifname] = $gateway; - $i++; } return($gateways_arr); } - -/* return a array with all gateway groups with name as key +/* + * Return an array with all gateway groups with name as key * All gateway groups will be processed before returning the array. -*/ + */ function return_gateway_groups_array() { global $config, $g; /* fetch the current gateways status */ - $gateways_status = return_gateways_status(); + $gateways_status = return_gateways_status(true); $gateways_arr = return_gateways_array(); $gateway_groups_array = array(); @@ -374,58 +358,49 @@ function return_gateway_groups_array() { foreach($config['gateways']['gateway_group'] as $group) { /* create array with group gateways members seperated by tier */ $tiers = array(); + $backupplan = array(); foreach($group['item'] as $item) { $itemsplit = explode("|", $item); $tier = $itemsplit[1]; $gwname = $itemsplit[0]; + + /* Do it here rather than reiterating again the group in case no member is up. */ + $backupplan[$tier] = $gwname; + /* check if the gateway is available before adding it to the array */ - foreach($gateways_status as $status) { - if ($status['name'] != $gwname) { - continue; - } + if (!empty($gateway_status[$gwname])) { + $gwdown = false; if (stristr($status['status'], "down")) { - $msg = "MONITOR: $gwname has high latency, removing from routing group"; + $msg = "MONITOR: {$gwname} has high latency, removing from routing group"; + $gwdown = true; + } else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) { + /* packet loss */ + $msg = "MONITOR: {$gwname} has packet loss, removing from routing group"; + $gwdown = true; + } else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) { + /* high latency */ + $msg = "MONITOR: {$gwname} has high latency, removing from routing group"; + $gwdown = true; + } + if ($gwdown == true) { log_error($msg); notify_via_growl($msg); - } elseif (stristr($status['status'], "loss")) { - if (strstr($group['trigger'], "loss")) { - /* packet loss */ - $msg = "MONITOR: $gwname has packet loss, removing from routing group"; - log_error($msg); - notify_via_growl($msg); - } else { - $tiers[$tier][] = $gwname; - } - } elseif (stristr($status['status'], "delay")) { - if (strstr($group['trigger'] , "latency")) { - /* high latency */ - $msg = "MONITOR: $gwname has high latency, removing from routing group"; - log_error($msg); - notify_via_growl($msg); - } else { - $tiers[$tier][] = $gwname; - } - } elseif ($status['status'] == "none") { + } else /* Online add member */ $tiers[$tier][] = $gwname; - } } } $tiers_count = count($tiers); if($tiers_count == 0) { /* Oh dear, we have no members! Engage Plan B */ - $msg = "All gateways are unavailable, proceeding with configured XML settings!"; + $msg = "Gateways status could not be determined, considering all as up/active."; log_error($msg); notify_via_growl($msg); - foreach($group['item'] as $item) { - $itemsplit = explode("|", $item); - $tier = $itemsplit[1]; - $gwname = $itemsplit[0]; - $tiers[$tier][] = $gwname; - } + $tiers = $backupplan; } /* sort the tiers array by the tier key */ ksort($tiers); + /* we do not really foreach the tiers as we stop after the first tier */ foreach($tiers as $tier) { /* process all gateways in this tier */ @@ -439,13 +414,14 @@ function return_gateway_groups_array() { $gatewayip = $gateway['gateway']; else if ($int <> "") $gatewayip = get_interface_gateway($gateway['friendlyiface']); - } - if (($int <> "") && is_ipaddr($gatewayip)) { - $groupmember = array(); - $groupmember['int'] = "$int"; - $groupmember['gwip'] = "$gatewayip"; - $groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1; - $gateway_groups_array[$group['name']][] = $groupmember; + + if (($int <> "") && is_ipaddr($gatewayip)) { + $groupmember = array(); + $groupmember['int'] = $int; + $groupmember['gwip'] = $gatewayip; + $groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1; + $gateway_groups_array[$group['name']][] = $groupmember; + } } } /* we should have the 1st available tier now, exit stage left */ @@ -518,7 +494,7 @@ function get_interface_gateway($interface, &$dynamic = false) { $gw = NULL; - $gwcfg = $config['interfaces'][$interface]; + $gwcfg =& $config['interfaces'][$interface]; if (is_ipaddr($gwcfg['gateway'])) $gw = $gwcfg['gateway']; else if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) { @@ -534,8 +510,7 @@ function get_interface_gateway($interface, &$dynamic = false) { if (!is_ipaddr($gw) && !is_ipaddr($gwcfg['ipaddr'])) { $realif = get_real_interface($interface); if (file_exists("{$g['tmp_path']}/{$realif}_router")) { - $gw = file_get_contents("{$g['tmp_path']}/{$realif}_router"); - $gw = rtrim($gw); + $gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n"); $dynamic = true; } } diff --git a/usr/local/sbin/ppp-linkdown b/usr/local/sbin/ppp-linkdown index 59b2ce0..8b09846 100755 --- a/usr/local/sbin/ppp-linkdown +++ b/usr/local/sbin/ppp-linkdown @@ -8,6 +8,6 @@ fi /usr/sbin/ngctl shutdown $1: /bin/rm -f /var/etc/nameserver_$1 # Do not remove gateway used during filter reload. -# /bin/rm -f /tmp/$1_router +/bin/rm -f /tmp/$1_router /bin/rm -f /tmp/$1up /usr/local/sbin/pfSctl -c 'service reload dns' diff --git a/usr/local/sbin/ppp-linkup b/usr/local/sbin/ppp-linkup index 67b0832..f1d7018 100755 --- a/usr/local/sbin/ppp-linkup +++ b/usr/local/sbin/ppp-linkup @@ -14,7 +14,7 @@ if [ $8 = "dns2" ]; then fi # let the configuration system know that the ip has changed. -/usr/local/sbin/pfSctl -c "'interface reload $1'" /bin/echo $4 > /tmp/$1_router /usr/bin/touch /tmp/$1up +/usr/local/sbin/pfSctl -c "'interface reload $1'" exit 0 |