Project

General

Profile

Download (36.8 KB) Statistics
| Branch: | Tag: | Revision:
1 17623ab5 Bill Marquette
<?php
2
/*
3 ce77a9c4 Phil Davis
	gwlb.inc
4
	Copyright (C) 2008 Bill Marquette, Seth Mos
5
	Copyright (C) 2010 Ermal Luçi
6
	All rights reserved.
7
8
	Redistribution and use in source and binary forms, with or without
9
	modification, are permitted provided that the following conditions are met:
10
11
	1. Redistributions of source code must retain the above copyright notice,
12
	this list of conditions and the following disclaimer.
13
14
	2. Redistributions in binary form must reproduce the above copyright
15
	notice, this list of conditions and the following disclaimer in the
16
	documentation and/or other materials provided with the distribution.
17
18
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
	POSSIBILITY OF SUCH DAMAGE.
28 c1191d5b Ermal
 */
29 6aa3723a Renato Botelho
30 c5e53ee6 jim-p
require_once("config.inc");
31 d55cba63 N0YB
require_once("rrd.inc");
32 17623ab5 Bill Marquette
33 69eefb50 Renato Botelho
/* Returns an array of default values used for dpinger */
34
function return_dpinger_defaults() {
35 14661668 Phil Davis
	return array(
36
		"latencylow" => "200",
37
		"latencyhigh" => "500",
38
		"losslow" => "10",
39
		"losshigh" => "20",
40 69eefb50 Renato Botelho
		"interval" => "250",
41 deff3aed Renato Botelho
		"loss_interval" => "1250",
42
		"time_period" => "30000",
43 69eefb50 Renato Botelho
		"alert_interval" => "1000");
44 a99547e4 Ermal
}
45 14661668 Phil Davis
46 69eefb50 Renato Botelho
function running_dpinger_processes() {
47
	global $g;
48 ffe76308 Seth Mos
49 69eefb50 Renato Botelho
	$pidfiles = glob("{$g['varrun_path']}/dpinger_*.pid");
50 cdcea13f Seth Mos
51 69eefb50 Renato Botelho
	$result = array();
52
	if ($pidfiles === FALSE) {
53
		return $result;
54 9ba87997 Phil Davis
	}
55 a99547e4 Ermal
56 69eefb50 Renato Botelho
	foreach ($pidfiles as $pidfile) {
57 c987a206 Renato Botelho
		if (preg_match('/^dpinger_(.+)_([^_]+)_([^_]+)\.pid$/',
58 73e3aa21 Renato Botelho
		    basename($pidfile), $matches)) {
59
			$socket_file = preg_replace('/\.pid$/', '.sock',
60
			    $pidfile);
61
			$result[$matches[1]] = array(
62
			    'srcip'    => $matches[2],
63
			    'targetip' => $matches[3],
64 b76cb978 Renato Botelho
			    'pidfile'  => $pidfile,
65 73e3aa21 Renato Botelho
			    'socket'   => $socket_file
66
			);
67
			unset($gwinfo);
68
		}
69 69eefb50 Renato Botelho
	}
70 cdcea13f Seth Mos
71 69eefb50 Renato Botelho
	return $result;
72 cdcea13f Seth Mos
}
73
74 69eefb50 Renato Botelho
/*
75
 * Stop one or more dpinger process
76
 * default parameter $gwname is '*' that will kill all running sessions
77
 * If a gateway name is passed, only this one will be killed
78
 */
79 73e3aa21 Renato Botelho
function stop_dpinger($gwname = '') {
80 69eefb50 Renato Botelho
	global $g;
81 cdcea13f Seth Mos
82 73e3aa21 Renato Botelho
	$running_processes = running_dpinger_processes();
83 cdcea13f Seth Mos
84 73e3aa21 Renato Botelho
	foreach ($running_processes as $running_gwname => $process) {
85
		if ($gwname != '' && $running_gwname != $gwname) {
86
			continue;
87
		}
88 cdcea13f Seth Mos
89 73e3aa21 Renato Botelho
		if (isvalidpid($process['pidfile'])) {
90
			killbypid($process['pidfile']);
91 69eefb50 Renato Botelho
		} else {
92 73e3aa21 Renato Botelho
			@unlink($process['pidfile']);
93 69eefb50 Renato Botelho
		}
94
	}
95 cdcea13f Seth Mos
}
96
97 69eefb50 Renato Botelho
function start_dpinger($gateway) {
98
	global $g;
99
100 73e3aa21 Renato Botelho
	if (!isset($gateway['gwifip'])) {
101
		return;
102
	}
103
104 69eefb50 Renato Botelho
	$dpinger_defaults = return_dpinger_defaults();
105
106 73e3aa21 Renato Botelho
	$pidfile = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
107
	    "{$gateway['gwifip']}_{$gateway['monitor']}.pid";
108
	$socket = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
109
	    "{$gateway['gwifip']}_{$gateway['monitor']}.sock";
110
	$alarm_cmd = "{$g['etc_path']}/rc.gateway_alarm";
111 69eefb50 Renato Botelho
112 73e3aa21 Renato Botelho
	$params  = "-S ";			/* Log warnings via syslog */
113 7e1d7724 Renato Botelho
	$params .= "-r 0 ";			/* Disable unused reporting thread */
114 73e3aa21 Renato Botelho
	$params .= "-i {$gateway['name']} ";	/* Identifier */
115
	$params .= "-B {$gateway['gwifip']} ";	/* Bind src address */
116
	$params .= "-p {$pidfile} ";		/* PID filename */
117
	$params .= "-u {$socket} ";		/* Status Socket */
118
	$params .= "-C \"{$alarm_cmd}\" ";	/* Command to run on alarm */
119 69eefb50 Renato Botelho
120
	$params .= "-s " .
121
	    (isset($gateway['interval']) && is_numeric($gateway['interval'])
122
	    ? $gateway['interval']
123
	    : $dpinger_defaults['interval']
124
	    ) . " ";
125
126
	$params .= "-l " .
127 0aeb97d2 Phil Davis
	    (isset($gateway['loss_interval']) && is_numeric($gateway['loss_interval'])
128 69eefb50 Renato Botelho
	    ?  $gateway['loss_interval']
129
	    : $dpinger_defaults['loss_interval']
130
	    ) . " ";
131
132
	$params .= "-t " .
133
	    (isset($gateway['time_period']) && is_numeric($gateway['time_period'])
134
	    ?  $gateway['time_period']
135
	    : $dpinger_defaults['time_period']
136
	    ) . " ";
137
138
	$params .= "-A " .
139
	    (isset($gateway['alert_interval']) && is_numeric($gateway['alert_interval'])
140
	    ?  $gateway['alert_interval']
141
	    : $dpinger_defaults['alert_interval']
142
	    ) . " ";
143
144
	$params .= "-D " .
145
	    (isset($gateway['latencyhigh']) && is_numeric($gateway['latencyhigh'])
146
	    ?  $gateway['latencyhigh']
147
	    : $dpinger_defaults['latencyhigh']
148
	    ) . " ";
149
150
	$params .= "-L " .
151
	    (isset($gateway['losshigh']) && is_numeric($gateway['losshigh'])
152
	    ?  $gateway['losshigh']
153
	    : $dpinger_defaults['losshigh']
154
	    ) . " ";
155
156 4fc47b2f Renato Botelho
	/* Make sure we don't end up with 2 process for the same GW */
157
	stop_dpinger($gateway['name']);
158
159 61c45d84 Renato Botelho
	/* Redirect stdout to /dev/null to avoid exec() to wait for dpinger */
160
	return mwexec("/usr/local/bin/dpinger {$params} {$gateway['monitor']} >/dev/null");
161 cdcea13f Seth Mos
}
162
163 69eefb50 Renato Botelho
/*
164 99c1e285 Chris Buechler
 * Starts dpinger processes and adds appropriate static routes for monitor IPs
165 69eefb50 Renato Botelho
 */
166
function setup_gateways_monitor() {
167
	global $config, $g;
168 cdcea13f Seth Mos
169 69eefb50 Renato Botelho
	$gateways_arr = return_gateways_array();
170
	if (!is_array($gateways_arr)) {
171
		log_error("No gateways to monitor. dpinger will not run.");
172
		stop_dpinger();
173
		return;
174
	}
175 cdcea13f Seth Mos
176 74c834f1 smos
	$monitor_ips = array();
177 69eefb50 Renato Botelho
	foreach ($gateways_arr as $gwname => $gateway) {
178 33c06ef7 Ermal
		/* Do not monitor if such was requested */
179 9ba87997 Phil Davis
		if (isset($gateway['monitor_disable'])) {
180 33c06ef7 Ermal
			continue;
181 9ba87997 Phil Davis
		}
182 3d471a14 Ermal
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
183 9ba87997 Phil Davis
			if (is_ipaddr($gateway['gateway'])) {
184 3f4e6035 Renato Botelho
				$gateways_arr[$gwname]['monitor'] = $gateway['gateway'];
185 9ba87997 Phil Davis
			} else { /* No chance to get an ip to monitor skip target. */
186 f31ab121 Ermal
				continue;
187 9ba87997 Phil Davis
			}
188 3d471a14 Ermal
		}
189 f31ab121 Ermal
190 f040882c Renato Botelho
		/* if the monitor address is already used before, skip */
191 9ba87997 Phil Davis
		if (in_array($gateway['monitor'], $monitor_ips)) {
192 74c834f1 smos
			continue;
193 9ba87997 Phil Davis
		}
194 f040882c Renato Botelho
195 69eefb50 Renato Botelho
		/* Interface ip is needed since dpinger will bind a socket to it.
196 9ba87997 Phil Davis
		 * However the config GUI should already have checked this and when
197 99c1e285 Chris Buechler
		 * PPPoE is used the IP address is set to "dynamic". So using is_ipaddrv4
198 8c7e38ff Camlin
		 * or is_ipaddrv6 to identify packet type would be wrong, especially as
199
		 * further checks (that can cope with the "dynamic" case) are present inside
200
		 * the if block. So using $gateway['ipprotocol'] is the better option.
201
		 */
202
		if ($gateway['ipprotocol'] == "inet") { // This is an IPv4 gateway...
203 640b3a9a Seth Mos
			$gwifip = find_interface_ip($gateway['interface'], true);
204 9ba87997 Phil Davis
			if (!is_ipaddrv4($gwifip)) {
205 e9d156fd Ermal
				continue; //Skip this target
206 9ba87997 Phil Davis
			}
207 32a9eb18 Ermal
208 9ba87997 Phil Davis
			if ($gwifip == "0.0.0.0") {
209 2d793d01 Phil Davis
				continue; //Skip this target - the gateway is still waiting for DHCP
210 9ba87997 Phil Davis
			}
211 2d793d01 Phil Davis
212 32a9eb18 Ermal
			/*
213
			 * If the gateway is the same as the monitor we do not add a
214
			 * route as this will break the routing table.
215
			 * Add static routes for each gateway with their monitor IP
216
			 * not strictly necessary but is a added level of protection.
217
			 */
218
			if (is_ipaddrv4($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
219
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
220 9ba87997 Phil Davis
				if (interface_isppp_type($gateway['friendlyiface'])) {
221 7a63d5d0 Ermal LUÇI
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
222
						" -iface " . escapeshellarg($gateway['interface']), true);
223 9ba87997 Phil Davis
				} else {
224 7a63d5d0 Ermal LUÇI
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
225
						" " . escapeshellarg($gateway['gateway']), true);
226 9ba87997 Phil Davis
				}
227 7a63d5d0 Ermal LUÇI
228
				pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp");
229 32a9eb18 Ermal
			}
230 8c7e38ff Camlin
		} else if ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway...
231 3f4e6035 Renato Botelho
			if (is_linklocal($gateway['gateway']) &&
232
			    get_ll_scope($gateway['gateway']) == '') {
233
				$gateways_arr[$gwname]['gateway'] .= '%' . $gateway['interface'];
234
			}
235
236
			if (is_linklocal($gateway['monitor'])) {
237
				if (get_ll_scope($gateway['monitor']) == '') {
238
					$gateways_arr[$gwname]['monitor'] .= '%' . $gateway['interface'];
239
				}
240
241
				$gwifip = find_interface_ipv6_ll($gateway['interface'], true);
242
243
				if (get_ll_scope($gwifip) == '') {
244
					$gwifip .= '%' . $gateway['interface'];
245 dd8d9bdc Camlin
				}
246 81a3b6f5 smos
			} else {
247
				$gwifip = find_interface_ipv6($gateway['interface'], true);
248
			}
249 3f6525c1 Renato Botelho
250 9ba87997 Phil Davis
			if (!is_ipaddrv6($gwifip)) {
251 e9d156fd Ermal
				continue; //Skip this target
252 9ba87997 Phil Davis
			}
253 32a9eb18 Ermal
254
			/*
255
			 * If the gateway is the same as the monitor we do not add a
256
			 * route as this will break the routing table.
257
			 * Add static routes for each gateway with their monitor IP
258
			 * not strictly necessary but is a added level of protection.
259
			 */
260 f4443dce Ermal
			if ($gateway['gateway'] != $gateway['monitor']) {
261 32a9eb18 Ermal
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
262 9ba87997 Phil Davis
				if (interface_isppp_type($gateway['friendlyiface'])) {
263 7a63d5d0 Ermal LUÇI
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
264
						" -iface " . escapeshellarg($gateway['interface']), true);
265 9ba87997 Phil Davis
				} else {
266 7a63d5d0 Ermal LUÇI
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
267
						" " . escapeshellarg($gateway['gateway']), true);
268 9ba87997 Phil Davis
				}
269 7a63d5d0 Ermal LUÇI
270
				pfSense_kill_states("::0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmpv6");
271 32a9eb18 Ermal
			}
272 9ba87997 Phil Davis
		} else {
273 e9d156fd Ermal
			continue;
274 9ba87997 Phil Davis
		}
275 3d471a14 Ermal
276 45eb8aeb Renato Botelho
		$monitor_ips[] = $gateway['monitor'];
277 69eefb50 Renato Botelho
		$gateways_arr[$gwname]['enable_dpinger'] = true;
278
		$gateways_arr[$gwname]['gwifip'] = $gwifip;
279
	}
280 3c6787ed N0YB
281 69eefb50 Renato Botelho
	stop_dpinger();
282 3c6787ed N0YB
283 69eefb50 Renato Botelho
	/* Start new processes */
284
	foreach ($gateways_arr as $gateway) {
285 3a335f07 Renato Botelho
		if (!isset($gateway['enable_dpinger'])) {
286
			continue;
287
		}
288
289
		if (start_dpinger($gateway) != 0) {
290 87b30cfa Renato Botelho
			log_error("Error starting gateway monitor for " .
291
			    $gateway['name']);
292 3c6787ed N0YB
		}
293 69eefb50 Renato Botelho
	}
294 3c6787ed N0YB
295 b42177b9 Renato Botelho
	return;
296 69eefb50 Renato Botelho
}
297 3c6787ed N0YB
298 69eefb50 Renato Botelho
function get_dpinger_status($gwname) {
299
	global $g;
300 3d471a14 Ermal
301 73e3aa21 Renato Botelho
	$running_processes = running_dpinger_processes();
302
303
	if (!isset($running_processes[$gwname])) {
304
		log_error("dpinger: No dpinger session running for gateway {$gwname}");
305
		return false;
306
	}
307
308
	$proc = $running_processes[$gwname];
309
	unset($running_processes);
310 81f19476 Renato Botelho
311 73e3aa21 Renato Botelho
	if (!file_exists($proc['socket'])) {
312
		log_error("dpinger: status socket {$proc['socket']} not found");
313 69eefb50 Renato Botelho
		return false;
314
	}
315 3d471a14 Ermal
316 73e3aa21 Renato Botelho
	$fp = stream_socket_client("unix://{$proc['socket']}", $errno, $errstr, 10);
317 69eefb50 Renato Botelho
	if (!$fp) {
318 73e3aa21 Renato Botelho
		log_error("dpinger: cannot connect to status socket {$proc['socket']} - $errstr ($errno)");
319 69eefb50 Renato Botelho
		return false;
320
	}
321 d55cba63 N0YB
322 69eefb50 Renato Botelho
	$status = '';
323
	while (!feof($fp)) {
324
		$status .= fgets($fp, 1024);
325 cdcea13f Seth Mos
	}
326 69eefb50 Renato Botelho
	fclose($fp);
327
328
	$r = array();
329
	list(
330 73e3aa21 Renato Botelho
	    $r['gwname'],
331 69eefb50 Renato Botelho
	    $r['latency_avg'],
332
	    $r['latency_stddev'],
333 73e3aa21 Renato Botelho
	    $r['loss']
334 69eefb50 Renato Botelho
	) = explode(' ', preg_replace('/\n/', '', $status));
335 cdcea13f Seth Mos
336 73e3aa21 Renato Botelho
	$r['srcip'] = $proc['srcip'];
337
	$r['targetip'] = $proc['targetip'];
338
339 69eefb50 Renato Botelho
	$gateways_arr = return_gateways_array();
340
	unset($gw);
341
	if (isset($gateways_arr[$gwname])) {
342
		$gw = $gateways_arr[$gwname];
343 746f0afb Ermal
	}
344 4f060616 Ermal
345 08e18c83 Renato Botelho
	$r['latency_avg'] = round($r['latency_avg']/1000, 3);
346
	$r['latency_stddev'] = round($r['latency_stddev']/1000, 3);
347
348 69eefb50 Renato Botelho
	$r['status'] = "none";
349
	if (isset($gw) && isset($gw['force_down'])) {
350
		$r['status'] = "force_down";
351
	} else if (isset($gw)) {
352 73e3aa21 Renato Botelho
		$settings = return_dpinger_defaults();
353
354
		$keys = array(
355
		    'latencylow',
356
		    'latencyhigh',
357
		    'losslow',
358
		    'losshigh'
359
		);
360
361
		/* Replace default values by user-defined */
362
		foreach ($keys as $key) {
363
			if (isset($gw[$key]) && is_numeric($gw[$key])) {
364
				$settings[$key] = $gw[$key];
365
			}
366 d8f89cce Renato Botelho
		}
367
368 73e3aa21 Renato Botelho
		if ($r['latency_avg'] > $settings['latencyhigh'] ||
369
		    $r['loss'] > $settings['losshigh']) {
370
			$r['status'] = "down";
371
		} else if ($r['latency_avg'] > $settings['latencylow']) {
372 69eefb50 Renato Botelho
			$r['status'] = "delay";
373 73e3aa21 Renato Botelho
		} else if ($r['loss'] > $settings['losslow']) {
374
			$r['status'] = "loss";
375 69eefb50 Renato Botelho
		}
376
	}
377
378
	return $r;
379 cdcea13f Seth Mos
}
380
381 0aeb97d2 Phil Davis
/* return the status of the dpinger targets as an array */
382 3d471a14 Ermal
function return_gateways_status($byname = false) {
383 ae9618af Ermal
	global $config, $g;
384 cdcea13f Seth Mos
385 69eefb50 Renato Botelho
	$dpinger_gws = running_dpinger_processes();
386 67ee1ec5 Ermal Luçi
	$status = array();
387 69eefb50 Renato Botelho
388
	$gateways_arr = return_gateways_array();
389
390 73e3aa21 Renato Botelho
	foreach ($dpinger_gws as $gwname => $gwdata) {
391 69eefb50 Renato Botelho
		$dpinger_status = get_dpinger_status($gwname);
392
		if ($dpinger_status === false) {
393
			continue;
394
		}
395
396 9ba87997 Phil Davis
		if ($byname == false) {
397 69eefb50 Renato Botelho
			$target = $dpinger_status['targetip'];
398 9ba87997 Phil Davis
		} else {
399 69eefb50 Renato Botelho
			$target = $gwname;
400 9ba87997 Phil Davis
		}
401 47c48e28 smos
402 dea0921d Ermal
		$status[$target] = array();
403 69eefb50 Renato Botelho
		$status[$target]['monitorip'] = $dpinger_status['targetip'];
404
		$status[$target]['srcip'] = $dpinger_status['srcip'];
405
		$status[$target]['name'] = $gwname;
406 0aeb97d2 Phil Davis
		$status[$target]['delay'] = empty($dpinger_status['latency_avg']) ? "0ms" : $dpinger_status['latency_avg'] . "ms";
407 69eefb50 Renato Botelho
		$status[$target]['loss'] = empty($dpinger_status['loss']) ? "0.0%" : round($dpinger_status['loss'], 1) . "%";
408
		$status[$target]['status'] = $dpinger_status['status'];
409 cdcea13f Seth Mos
	}
410 68f291ff Ermal
411 47c48e28 smos
	/* tack on any gateways that have monitoring disabled
412
	 * or are down, which could cause gateway groups to fail */
413 16106d2e smos
	$gateways_arr = return_gateways_array();
414 9ba87997 Phil Davis
	foreach ($gateways_arr as $gwitem) {
415
		if (!isset($gwitem['monitor_disable'])) {
416 fd34d6a9 Ermal
			continue;
417 9ba87997 Phil Davis
		}
418 69eefb50 Renato Botelho
		if (!is_ipaddr($gwitem['monitor'])) {
419 fd34d6a9 Ermal
			$realif = $gwitem['interface'];
420
			$tgtip = get_interface_gateway($realif);
421 9ba87997 Phil Davis
			if (!is_ipaddr($tgtip)) {
422 fd34d6a9 Ermal
				$tgtip = "none";
423 9ba87997 Phil Davis
			}
424 fd34d6a9 Ermal
			$srcip = find_interface_ip($realif);
425
		} else {
426 69eefb50 Renato Botelho
			$tgtip = $gwitem['monitor'];
427 fd34d6a9 Ermal
			$srcip = find_interface_ip($realif);
428
		}
429 9ba87997 Phil Davis
		if ($byname == true) {
430 fd34d6a9 Ermal
			$target = $gwitem['name'];
431 9ba87997 Phil Davis
		} else {
432 fd34d6a9 Ermal
			$target = $tgtip;
433 9ba87997 Phil Davis
		}
434 fd34d6a9 Ermal
435
		/* failsafe for down interfaces */
436 9ba87997 Phil Davis
		if ($target == "none") {
437 fd34d6a9 Ermal
			$target = $gwitem['name'];
438
			$status[$target]['name'] = $gwitem['name'];
439
			$status[$target]['delay'] = "0.0ms";
440
			$status[$target]['loss'] = "100.0%";
441
			$status[$target]['status'] = "down";
442
		} else {
443
			$status[$target]['monitorip'] = $tgtip;
444
			$status[$target]['srcip'] = $srcip;
445
			$status[$target]['name'] = $gwitem['name'];
446
			$status[$target]['delay'] = "0.0ms";
447
			$status[$target]['loss'] = "0.0%";
448
			$status[$target]['status'] = "none";
449 16106d2e smos
		}
450
	}
451 cdcea13f Seth Mos
	return($status);
452 17623ab5 Bill Marquette
}
453
454 2328dcc5 Seth Mos
/* Return all configured gateways on the system */
455 06b8d43c Renato Botelho
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
456 8d3556c2 gnhb
	global $config, $g;
457 7901dff5 Ermal Luçi
458 c66b4242 Seth Mos
	$gateways_arr = array();
459 8d848bdf Phil Davis
	$gateways_arr_temp = array();
460 c66b4242 Seth Mos
461 74c834f1 smos
	$found_defaultv4 = 0;
462
	$found_defaultv6 = 0;
463
464 33e71f10 jim-p
	// Ensure the interface cache is up to date first
465
	$interfaces = get_interface_arr(true);
466 3930a9c0 smos
	$interfaces_v4 = array();
467
	$interfaces_v6 = array();
468
469 23d9f686 Renato Botelho
	$i = -1;
470 3d471a14 Ermal
	/* Process/add all the configured gateways. */
471 ef05ae5f Ermal
	if (is_array($config['gateways']['gateway_item'])) {
472 1500614c Ermal
		foreach ($config['gateways']['gateway_item'] as $gateway) {
473 23d9f686 Renato Botelho
			/* Increment it here to do not skip items */
474
			$i++;
475
476 06b8d43c Renato Botelho
			if (empty($config['interfaces'][$gateway['interface']])) {
477 9ba87997 Phil Davis
				if ($inactive === false) {
478 06b8d43c Renato Botelho
					continue;
479 9ba87997 Phil Davis
				} else {
480 06b8d43c Renato Botelho
					$gateway['inactive'] = true;
481 9ba87997 Phil Davis
				}
482 06b8d43c Renato Botelho
			}
483 3930a9c0 smos
			$wancfg = $config['interfaces'][$gateway['interface']];
484 1500614c Ermal
485
			/* skip disabled interfaces */
486 9ba87997 Phil Davis
			if ($disabled === false && (!isset($wancfg['enable']))) {
487 1500614c Ermal
				continue;
488 9ba87997 Phil Davis
			}
489 c1d36d26 smos
490 3930a9c0 smos
			/* if the gateway is dynamic and we can find the IPv4, Great! */
491 d07bc322 Renato Botelho
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
492 1500614c Ermal
				if ($gateway['ipprotocol'] == "inet") {
493
					/* we know which interfaces is dynamic, this should be made a function */
494 65cfd0ca Renato Botelho
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
495
					/* no IP address found, set to dynamic */
496 9ba87997 Phil Davis
					if (!is_ipaddrv4($gateway['gateway'])) {
497 65cfd0ca Renato Botelho
						$gateway['gateway'] = "dynamic";
498 9ba87997 Phil Davis
					}
499 65cfd0ca Renato Botelho
					$gateway['dynamic'] = true;
500 74c834f1 smos
				}
501 c1d36d26 smos
502 d07bc322 Renato Botelho
				/* if the gateway is dynamic and we can find the IPv6, Great! */
503 8e78c82c Renato Botelho
				else if ($gateway['ipprotocol'] == "inet6") {
504 1500614c Ermal
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
505 65cfd0ca Renato Botelho
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
506 d07bc322 Renato Botelho
					/* no IPv6 address found, set to dynamic */
507 9ba87997 Phil Davis
					if (!is_ipaddrv6($gateway['gateway'])) {
508 d07bc322 Renato Botelho
						$gateway['gateway'] = "dynamic";
509 9ba87997 Phil Davis
					}
510 65cfd0ca Renato Botelho
					$gateway['dynamic'] = true;
511 7671c940 Seth Mos
				}
512 1500614c Ermal
			} else {
513
				/* getting this detection right is hard at this point because we still don't
514
				 * store the address family in the gateway item */
515 9ba87997 Phil Davis
				if (is_ipaddrv4($gateway['gateway'])) {
516 1500614c Ermal
					$gateway['ipprotocol'] = "inet";
517 9ba87997 Phil Davis
				} else if (is_ipaddrv6($gateway['gateway'])) {
518 1500614c Ermal
					$gateway['ipprotocol'] = "inet6";
519 9ba87997 Phil Davis
				}
520 2328dcc5 Seth Mos
			}
521 c1d36d26 smos
522 9ba87997 Phil Davis
			if (isset($gateway['monitor_disable'])) {
523 33c06ef7 Ermal
				$gateway['monitor_disable'] = true;
524 9ba87997 Phil Davis
			} else if (empty($gateway['monitor'])) {
525 2328dcc5 Seth Mos
				$gateway['monitor'] = $gateway['gateway'];
526 9ba87997 Phil Davis
			}
527 3d471a14 Ermal
528 883c53c9 Ermal Lu?i
			$gateway['friendlyiface'] = $gateway['interface'];
529 c1d36d26 smos
530
			/* special treatment for tunnel interfaces */
531 1500614c Ermal
			if ($gateway['ipprotocol'] == "inet6") {
532 33e71f10 jim-p
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
533 1500614c Ermal
				$interfaces_v6[$gateway['friendlyiface']] = $gateway['friendlyiface'];
534
			} else {
535 33e71f10 jim-p
				$gateway['interface'] = get_real_interface($gateway['interface'], "all", false, false);
536 1500614c Ermal
				$interfaces_v4[$gateway['friendlyiface']] = $gateway['friendlyiface'];
537
			}
538 74c834f1 smos
539
			/* entry has a default flag, use it */
540
			if (isset($gateway['defaultgw'])) {
541 1500614c Ermal
				if ($gateway['ipprotocol'] == "inet") {
542 74c834f1 smos
					$gateway['defaultgw'] = true;
543
					$found_defaultv4 = 1;
544 1500614c Ermal
				} else if ($gateway['ipprotocol'] == "inet6") {
545 74c834f1 smos
					$gateway['defaultgw'] = true;
546
					$found_defaultv6 = 1;
547
				}
548
			}
549 3d471a14 Ermal
			/* include the gateway index as the attribute */
550
			$gateway['attribute'] = $i;
551 2328dcc5 Seth Mos
552 8d848bdf Phil Davis
			/* Remember all the gateway names, even ones to be skipped because they are disabled. */
553
			/* Then we can easily know and match them later when attempting to add dynamic gateways to the list. */
554
			$gateways_arr_temp[$gateway['name']] = $gateway;
555
556
			/* skip disabled gateways if the caller has not asked for them to be returned. */
557 9ba87997 Phil Davis
			if (!($disabled === false && isset($gateway['disabled']))) {
558 8d848bdf Phil Davis
				$gateways_arr[$gateway['name']] = $gateway;
559 9ba87997 Phil Davis
			}
560 2328dcc5 Seth Mos
		}
561 c1d36d26 smos
	}
562 1500614c Ermal
	unset($gateway);
563 883c53c9 Ermal Lu?i
564 ef05ae5f Ermal
	/* Loop through all interfaces with a gateway and add it to a array */
565 9ba87997 Phil Davis
	if ($disabled == false) {
566 ef05ae5f Ermal
		$iflist = get_configured_interface_with_descr();
567 9ba87997 Phil Davis
	} else {
568 ef05ae5f Ermal
		$iflist = get_configured_interface_with_descr(false, true);
569 9ba87997 Phil Davis
	}
570 ef05ae5f Ermal
571 c3a0d2a5 Seth Mos
	/* Process/add dynamic v4 gateways. */
572 086cf944 Phil Davis
	foreach ($iflist as $ifname => $friendly) {
573
		if (!interface_has_gateway($ifname)) {
574 883c53c9 Ermal Lu?i
			continue;
575 9ba87997 Phil Davis
		}
576 3d471a14 Ermal
577 9ba87997 Phil Davis
		if (empty($config['interfaces'][$ifname])) {
578 86df2846 jim-p
			continue;
579 9ba87997 Phil Davis
		}
580 86df2846 jim-p
581
		$ifcfg = &$config['interfaces'][$ifname];
582 9ba87997 Phil Davis
		if (!isset($ifcfg['enable'])) {
583 e62fe748 Ermal
			continue;
584 9ba87997 Phil Davis
		}
585 e62fe748 Ermal
586 9ba87997 Phil Davis
		if (!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr'])) {
587 74c834f1 smos
			continue;
588 9ba87997 Phil Davis
		}
589 3930a9c0 smos
590 9ba87997 Phil Davis
		if (isset($interfaces_v4[$ifname])) {
591 3930a9c0 smos
			continue;
592 9ba87997 Phil Davis
		}
593 f040882c Renato Botelho
594 74c834f1 smos
		$ctype = "";
595 9ba87997 Phil Davis
		switch ($ifcfg['ipaddr']) {
596 74c834f1 smos
			case "dhcp":
597
			case "pppoe":
598
			case "pptp":
599 b2ff5d17 smos
			case "ppp":
600 74c834f1 smos
				$ctype = strtoupper($ifcfg['ipaddr']);
601
				break;
602 daac437f jim-p
			default:
603 11fb4543 Chris Buechler
				$tunnelif = substr($ifcfg['if'], 0, 3);
604 6c07db48 Phil Davis
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
605 687ff78c Chris Buechler
					// if current iface is an ovpn server endpoint then check its type, skip tap only
606
					if (substr($ifcfg['if'], 4, 1) == 's') {
607
						$ovpnid = substr($ifcfg['if'], 5);
608
						if (is_array($config['openvpn']['openvpn-server'])) {
609
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
610
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
611 9ba87997 Phil Davis
									if ($ovpnserverconf['dev_mode'] == "tap") {
612 687ff78c Chris Buechler
										continue 3;
613 9ba87997 Phil Davis
									}
614 687ff78c Chris Buechler
								}
615
							}
616
						}
617
					}
618 daac437f jim-p
					$ctype = "VPNv4";
619 9ba87997 Phil Davis
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
620 bac17444 Chris Buechler
					$ctype = "TUNNELv4";
621 9ba87997 Phil Davis
				}
622 daac437f jim-p
				break;
623 74c834f1 smos
		}
624
		$ctype = "_". strtoupper($ctype);
625
626 883c53c9 Ermal Lu?i
		$gateway = array();
627
		$gateway['dynamic'] = false;
628 c3a0d2a5 Seth Mos
		$gateway['ipprotocol'] = "inet";
629 883c53c9 Ermal Lu?i
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
630
		$gateway['interface'] = get_real_interface($ifname);
631
		$gateway['friendlyiface'] = $ifname;
632 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
633 883c53c9 Ermal Lu?i
		$gateway['attribute'] = "system";
634 f040882c Renato Botelho
635 74c834f1 smos
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
636 999111cb Ermal
			$gateway['defaultgw'] = true;
637
			$gateway['dynamic'] = true;
638 74c834f1 smos
			$found_defaultv4 = 1;
639 999111cb Ermal
		}
640 883c53c9 Ermal Lu?i
		/* Loopback dummy for dynamic interfaces without a IP */
641 9ba87997 Phil Davis
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true) {
642 999111cb Ermal
			$gateway['gateway'] = "dynamic";
643 9ba87997 Phil Davis
		}
644 3439b033 Seth Mos
645 8d848bdf Phil Davis
		/* automatically skip known static and dynamic gateways that were previously processed */
646 9ba87997 Phil Davis
		foreach ($gateways_arr_temp as $gateway_item) {
647 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
648 918bdf0d Phil Davis
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
649 9ba87997 Phil Davis
				continue 2;
650
			}
651 883c53c9 Ermal Lu?i
		}
652 c66b4242 Seth Mos
653 9ba87997 Phil Davis
		if (is_ipaddrv4($gateway['gateway'])) {
654 883c53c9 Ermal Lu?i
			$gateway['monitor'] = $gateway['gateway'];
655 9ba87997 Phil Davis
		}
656 c65e1e0d Ermal
657 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
658 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
659
	}
660 1500614c Ermal
	unset($gateway);
661 c3a0d2a5 Seth Mos
662
	/* Process/add dynamic v6 gateways. */
663 086cf944 Phil Davis
	foreach ($iflist as $ifname => $friendly) {
664 0715ad50 jim-p
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
665 9ba87997 Phil Davis
		if (!isset($config['system']['ipv6allow'])) {
666 0715ad50 jim-p
			break;
667 9ba87997 Phil Davis
		}
668 0715ad50 jim-p
669 086cf944 Phil Davis
		if (!interface_has_gatewayv6($ifname)) {
670 c3a0d2a5 Seth Mos
			continue;
671 9ba87997 Phil Davis
		}
672 c3a0d2a5 Seth Mos
673 9ba87997 Phil Davis
		if (empty($config['interfaces'][$ifname])) {
674 c3a0d2a5 Seth Mos
			continue;
675 9ba87997 Phil Davis
		}
676 c3a0d2a5 Seth Mos
677
		$ifcfg = &$config['interfaces'][$ifname];
678 9ba87997 Phil Davis
		if (!isset($ifcfg['enable'])) {
679 74c834f1 smos
			continue;
680 9ba87997 Phil Davis
		}
681 74c834f1 smos
682 9ba87997 Phil Davis
		if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
683 1500614c Ermal
			continue;
684 9ba87997 Phil Davis
		}
685 f040882c Renato Botelho
686 9ba87997 Phil Davis
		if (isset($interfaces_v6[$ifname])) {
687 3930a9c0 smos
			continue;
688 9ba87997 Phil Davis
		}
689 3930a9c0 smos
690 74c834f1 smos
		$ctype = "";
691 9ba87997 Phil Davis
		switch ($ifcfg['ipaddrv6']) {
692 c0b1bc81 smos
			case "slaac":
693 74c834f1 smos
			case "dhcp6":
694
			case "6to4":
695
			case "6rd":
696
				$ctype = strtoupper($ifcfg['ipaddrv6']);
697
				break;
698 daac437f jim-p
			default:
699 bf36dafa Renato Botelho
				$tunnelif = substr($ifcfg['if'], 0, 3);
700 6c07db48 Phil Davis
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
701 687ff78c Chris Buechler
					// if current iface is an ovpn server endpoint then check its type, skip tap only
702
					if (substr($ifcfg['if'], 4, 1) == 's') {
703
						$ovpnid = substr($ifcfg['if'], 5);
704
						if (is_array($config['openvpn']['openvpn-server'])) {
705
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
706
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
707 9ba87997 Phil Davis
									if ($ovpnserverconf['dev_mode'] == "tap") {
708 687ff78c Chris Buechler
										continue 3;
709 9ba87997 Phil Davis
									}
710 687ff78c Chris Buechler
								}
711
							}
712
						}
713
					}
714 daac437f jim-p
					$ctype = "VPNv6";
715 9ba87997 Phil Davis
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
716 c32a6b82 Ermal
					$ctype = "TUNNELv6";
717 9ba87997 Phil Davis
				}
718 daac437f jim-p
				break;
719 74c834f1 smos
		}
720
		$ctype = "_". strtoupper($ctype);
721 c3a0d2a5 Seth Mos
722
		$gateway = array();
723
		$gateway['dynamic'] = false;
724
		$gateway['ipprotocol'] = "inet6";
725
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
726 909de400 Ermal
		$gateway['interface'] = get_real_interface($ifname, "inet6");
727 9ba87997 Phil Davis
		switch ($ifcfg['ipaddrv6']) {
728 d500e296 smos
			case "6rd":
729 909de400 Ermal
			case "6to4":
730 d500e296 smos
				$gateway['dynamic'] = "default";
731
				break;
732
		}
733 c3a0d2a5 Seth Mos
		$gateway['friendlyiface'] = $ifname;
734 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
735 c3a0d2a5 Seth Mos
		$gateway['attribute'] = "system";
736 f040882c Renato Botelho
737 6c07db48 Phil Davis
		if (($gateway['dynamic'] === "default") && ($found_defaultv6 == 0)) {
738 c3a0d2a5 Seth Mos
			$gateway['defaultgw'] = true;
739
			$gateway['dynamic'] = true;
740 74c834f1 smos
			$found_defaultv6 = 1;
741 c3a0d2a5 Seth Mos
		}
742
743
		/* Loopback dummy for dynamic interfaces without a IP */
744 9ba87997 Phil Davis
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true) {
745 d07bc322 Renato Botelho
			$gateway['gateway'] = "dynamic";
746 9ba87997 Phil Davis
		}
747 c3a0d2a5 Seth Mos
748 8d848bdf Phil Davis
		/* automatically skip known static and dynamic gateways that were previously processed */
749 9ba87997 Phil Davis
		foreach ($gateways_arr_temp as $gateway_item) {
750 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
751 918bdf0d Phil Davis
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
752 9ba87997 Phil Davis
				continue 2;
753
			}
754 c3a0d2a5 Seth Mos
		}
755
756 9ba87997 Phil Davis
		if (is_ipaddrv6($gateway['gateway'])) {
757 c3a0d2a5 Seth Mos
			$gateway['monitor'] = $gateway['gateway'];
758 9ba87997 Phil Davis
		}
759 c3a0d2a5 Seth Mos
760 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
761 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
762 c66b4242 Seth Mos
	}
763 1500614c Ermal
	unset($gateway);
764 6fdea6a2 smos
765 08c3810c Renato Botelho
	/* FIXME: Should this be enabled.
766
	 * Some interface like wan might be default but have no info recorded
767
	 * the config. */
768
	/* this is a fallback if all else fails and we want to get packets out @smos */
769
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
770
		foreach ($gateways_arr as &$gateway) {
771
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
772
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
773
					$gateway['defaultgw'] = true;
774
					$found_defaultv4 = 1;
775
				}
776
			}
777 6704590b Ermal
			else if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
778 08c3810c Renato Botelho
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
779
					$gateway['defaultgw'] = true;
780
					$found_defaultv6 = 1;
781
				}
782
			}
783
		}
784
	}
785
786 9ba87997 Phil Davis
	if ($localhost === true) {
787 6fdea6a2 smos
		/* attach localhost for Null routes */
788
		$gwlo4 = array();
789
		$gwlo4['name'] = "Null4";
790
		$gwlo4['interface'] = "lo0";
791
		$gwlo4['ipprotocol'] = "inet";
792
		$gwlo4['gateway'] = "127.0.0.1";
793
		$gwlo6 = array();
794
		$gwlo6['name'] = "Null6";
795
		$gwlo6['interface'] = "lo0";
796
		$gwlo6['ipprotocol'] = "inet6";
797
		$gwlo6['gateway'] = "::1";
798
		$gateways_arr['Null4'] = $gwlo4;
799
		$gateways_arr['Null6'] = $gwlo6;
800
	}
801 c66b4242 Seth Mos
	return($gateways_arr);
802
}
803
804 fd3515f2 jim-p
function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) {
805
	global $config, $g;
806
	/*
807
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
808
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
809
	 */
810 894a0159 Ermal
	$upgw = '';
811
	$dfltgwname = '';
812 fd3515f2 jim-p
	$dfltgwdown = false;
813
	$dfltgwfound = false;
814
	foreach ($gateways_arr as $gwname => $gwsttng) {
815
		if (($gwsttng['ipprotocol'] == $ipprotocol) && isset($gwsttng['defaultgw'])) {
816
			$dfltgwfound = true;
817
			$dfltgwname = $gwname;
818 23cb4055 Chris Buechler
			if (!isset($gwsttng['monitor_disable']) && $gateways_status[$gwname]['status'] != "none") {
819 fd3515f2 jim-p
				$dfltgwdown = true;
820 9ba87997 Phil Davis
			}
821 fd3515f2 jim-p
		}
822
		/* Keep a record of the last up gateway */
823
		/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
824 23cb4055 Chris Buechler
		if (empty($upgw) && ($gwsttng['ipprotocol'] == $ipprotocol) && (isset($gwsttng['monitor_disable']) || $gateways_status[$gwname]['status'] == "none") && $gwsttng[$gwname]['friendlyiface'] != "lan") {
825 fd3515f2 jim-p
			$upgw = $gwname;
826 9ba87997 Phil Davis
		}
827
		if ($dfltgwdown == true && !empty($upgw)) {
828 fd3515f2 jim-p
			break;
829 9ba87997 Phil Davis
		}
830 fd3515f2 jim-p
	}
831
	if ($dfltgwfound == false) {
832
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
833 9ba87997 Phil Davis
		if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down")) {
834 fd3515f2 jim-p
			$dfltgwdown = true;
835 9ba87997 Phil Davis
		}
836 fd3515f2 jim-p
	}
837
	if ($dfltgwdown == true && !empty($upgw)) {
838 9ba87997 Phil Davis
		if ($gateways_arr[$upgw]['gateway'] == "dynamic") {
839 fd3515f2 jim-p
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
840 9ba87997 Phil Davis
		}
841 fd3515f2 jim-p
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
842
			log_error("Default gateway down setting {$upgw} as default!");
843 9ba87997 Phil Davis
			if (is_ipaddrv6($gateways_arr[$upgw]['gateway'])) {
844 fd3515f2 jim-p
				$inetfamily = "-inet6";
845
			} else {
846
				$inetfamily = "-inet";
847
			}
848
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
849
		}
850 fea0b652 Ermal LUÇI
	} else if (!empty($dfltgwname)) {
851 96fcabaa Renato Botelho
		$defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n");
852 9ba87997 Phil Davis
		if ($ipprotocol == 'inet6' && !is_ipaddrv6($gateways_arr[$dfltgwname]['gateway'])) {
853 894a0159 Ermal
			return;
854 9ba87997 Phil Davis
		}
855
		if ($ipprotocol == 'inet' && !is_ipaddrv4($gateways_arr[$dfltgwname]['gateway'])) {
856 894a0159 Ermal
			return;
857 9ba87997 Phil Davis
		}
858
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway']) {
859 894a0159 Ermal
			mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}");
860 9ba87997 Phil Davis
		}
861 fd3515f2 jim-p
	}
862
}
863
864 3d471a14 Ermal
/*
865
 * Return an array with all gateway groups with name as key
866 fd8eeda5 Seth Mos
 * All gateway groups will be processed before returning the array.
867 3d471a14 Ermal
 */
868 fd8eeda5 Seth Mos
function return_gateway_groups_array() {
869 962625aa Ermal
	global $config, $g;
870 fd8eeda5 Seth Mos
871
	/* fetch the current gateways status */
872 3d471a14 Ermal
	$gateways_status = return_gateways_status(true);
873 fd8eeda5 Seth Mos
	$gateways_arr = return_gateways_array();
874
	$gateway_groups_array = array();
875
876 7af360ce Ermal
	if (isset($config['system']['gw_switch_default'])) {
877 fd3515f2 jim-p
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
878
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
879 ee7f1647 Ermal
	}
880 fd8eeda5 Seth Mos
	if (is_array($config['gateways']['gateway_group'])) {
881 1500614c Ermal
		$carplist = get_configured_carp_interface_list();
882
		foreach ($config['gateways']['gateway_group'] as $group) {
883 5aa68a55 Renato Botelho
			/* create array with group gateways members separated by tier */
884 fd8eeda5 Seth Mos
			$tiers = array();
885 3d471a14 Ermal
			$backupplan = array();
886 1500614c Ermal
			$gwvip_arr = array();
887
			foreach ($group['item'] as $item) {
888 dea0921d Ermal
				list($gwname, $tier, $vipname) = explode("|", $item);
889 1500614c Ermal
890
				if (is_ipaddr($carplist[$vipname])) {
891 9ba87997 Phil Davis
					if (!is_array($gwvip_arr[$group['name']])) {
892 1500614c Ermal
						$gwvip_arr[$group['name']] = array();
893 9ba87997 Phil Davis
					}
894 ab1112da smos
					$gwvip_arr[$group['name']][$gwname] = $vipname;
895 1500614c Ermal
				}
896 3d471a14 Ermal
897
				/* Do it here rather than reiterating again the group in case no member is up. */
898 9ba87997 Phil Davis
				if (!is_array($backupplan[$tier])) {
899 dea0921d Ermal
					$backupplan[$tier] = array();
900 9ba87997 Phil Davis
				}
901 d8bf779b Ermal
				$backupplan[$tier][] = $gwname;
902 3d471a14 Ermal
903 fd8eeda5 Seth Mos
				/* check if the gateway is available before adding it to the array */
904 e0ba24f7 smos
				if (is_array($gateways_status[$gwname])) {
905 54b78cc1 Ermal
					$status = $gateways_status[$gwname];
906 3d471a14 Ermal
					$gwdown = false;
907 9af4b31b Ermal
					if (stristr($status['status'], "down")) {
908 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s is down, omitting from routing group {$group['name']}"), $gwname);
909 3d471a14 Ermal
						$gwdown = true;
910
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
911
						/* packet loss */
912 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s has packet loss, omitting from routing group {$group['name']}"), $gwname);
913 3d471a14 Ermal
						$gwdown = true;
914
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
915
						/* high latency */
916 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s has high latency, omitting from routing group {$group['name']}"), $gwname);
917 3d471a14 Ermal
						$gwdown = true;
918
					}
919
					if ($gwdown == true) {
920 9f1d61d3 Scott Ullrich
						log_error($msg);
921
						notify_via_growl($msg);
922 10c3d4c0 Scott Ullrich
						notify_via_smtp($msg);
923 e0ba24f7 smos
					} else {
924 857ce5f3 Seth Mos
						/* Online add member */
925 9ba87997 Phil Davis
						if (!is_array($tiers[$tier])) {
926 dea0921d Ermal
							$tiers[$tier] = array();
927 9ba87997 Phil Davis
						}
928 857ce5f3 Seth Mos
						$tiers[$tier][] = $gwname;
929 e0ba24f7 smos
					}
930 9ba87997 Phil Davis
				} else if (isset($gateways_arr[$gwname]['monitor_disable'])) {
931 33c06ef7 Ermal
					$tiers[$tier][] = $gwname;
932 9ba87997 Phil Davis
				}
933 fd8eeda5 Seth Mos
			}
934
			$tiers_count = count($tiers);
935 1500614c Ermal
			if ($tiers_count == 0) {
936 fd8eeda5 Seth Mos
				/* Oh dear, we have no members! Engage Plan B */
937 285ef132 Ermal LUÇI
				if (!platform_booting()) {
938 50006cca PiBa-NL
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
939 9132ae35 Ermal
					log_error($msg);
940
					notify_via_growl($msg);
941 72b4a1e8 jim-p
					//notify_via_smtp($msg);
942 9132ae35 Ermal
				}
943 3d471a14 Ermal
				$tiers = $backupplan;
944 fd8eeda5 Seth Mos
			}
945 09ae0c17 Seth Mos
			/* sort the tiers array by the tier key */
946
			ksort($tiers);
947 3d471a14 Ermal
948 fd8eeda5 Seth Mos
			/* we do not really foreach the tiers as we stop after the first tier */
949 1500614c Ermal
			foreach ($tiers as $tieridx => $tier) {
950 fd8eeda5 Seth Mos
				/* process all gateways in this tier */
951 1500614c Ermal
				foreach ($tier as $member) {
952 fd8eeda5 Seth Mos
					/* determine interface gateway */
953 5f53260a Ermal
					if (isset($gateways_arr[$member])) {
954
						$gateway = $gateways_arr[$member];
955
						$int = $gateway['interface'];
956
						$gatewayip = "";
957 9ba87997 Phil Davis
						if (is_ipaddr($gateway['gateway'])) {
958 5f53260a Ermal
							$gatewayip = $gateway['gateway'];
959 9ba87997 Phil Davis
						} else if (!empty($int)) {
960 5f53260a Ermal
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
961 9ba87997 Phil Davis
						}
962 f040882c Renato Botelho
963 f60003fa Phil Davis
						if (!empty($int)) {
964 44b054ce smos
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
965 f60003fa Phil Davis
							if (is_ipaddr($gatewayip)) {
966
								$groupmember = array();
967 6c07db48 Phil Davis
								$groupmember['int'] = $int;
968
								$groupmember['gwip'] = $gatewayip;
969
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
970 9ba87997 Phil Davis
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member])) {
971 f60003fa Phil Davis
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
972 9ba87997 Phil Davis
								}
973 f60003fa Phil Davis
								$gateway_groups_array[$group['name']][] = $groupmember;
974
							}
975 3d471a14 Ermal
						}
976 fd8eeda5 Seth Mos
					}
977
				}
978
				/* we should have the 1st available tier now, exit stage left */
979 9ba87997 Phil Davis
				if (count($gateway_groups_array[$group['name']]) > 0) {
980 47c48e28 smos
					break;
981 9ba87997 Phil Davis
				} else {
982 1500614c Ermal
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
983 9ba87997 Phil Davis
				}
984 fd8eeda5 Seth Mos
			}
985
		}
986
	}
987 1500614c Ermal
988 fe22a89b Ermal
	return ($gateway_groups_array);
989 fd8eeda5 Seth Mos
}
990
991 2468ae76 Scott Ullrich
/* Update DHCP WAN Interface ip address in gateway group item */
992
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
993
	global $config, $g;
994 9ba87997 Phil Davis
	foreach ($config['gateways']['gateway_item'] as & $gw) {
995
		if ($gw['interface'] == $interface) {
996 2468ae76 Scott Ullrich
			$current_gw = get_interface_gateway($interface);
997 9ba87997 Phil Davis
			if ($gw['gateway'] <> $current_gw) {
998 2468ae76 Scott Ullrich
				$gw['gateway'] = $current_gw;
999
				$changed = true;
1000
			}
1001
		}
1002
	}
1003 9ba87997 Phil Davis
	if ($changed && $current_gw) {
1004 addc0439 Renato Botelho
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
1005 9ba87997 Phil Davis
	}
1006 2468ae76 Scott Ullrich
}
1007 fd8eeda5 Seth Mos
1008 028ff8f8 Phil Davis
function lookup_gateway_ip_by_name($name, $disabled = false) {
1009 fe22a89b Ermal
1010 028ff8f8 Phil Davis
	$gateways_arr = return_gateways_array($disabled, true);
1011 f040882c Renato Botelho
	foreach ($gateways_arr as $gname => $gw) {
1012 9ba87997 Phil Davis
		if ($gw['name'] === $name || $gname === $name) {
1013 f040882c Renato Botelho
			return $gw['gateway'];
1014 9ba87997 Phil Davis
		}
1015 f040882c Renato Botelho
	}
1016 66a96e72 Ermal
1017
	return false;
1018 6dc3a5c2 Ermal Lu?i
}
1019
1020
function lookup_gateway_monitor_ip_by_name($name) {
1021 fe22a89b Ermal
1022 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1023 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
1024
		$gateway = $gateways_arr[$name];
1025 9ba87997 Phil Davis
		if (!is_ipaddr($gateway['monitor'])) {
1026 68f291ff Ermal
			return $gateway['gateway'];
1027 9ba87997 Phil Davis
		}
1028 6dc3a5c2 Ermal Lu?i
1029 9fd19334 gnhb
		return $gateway['monitor'];
1030 f040882c Renato Botelho
	}
1031 fe22a89b Ermal
1032 f040882c Renato Botelho
	return (false);
1033 6dc3a5c2 Ermal Lu?i
}
1034
1035
function lookup_gateway_interface_by_name($name) {
1036
1037 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1038 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
1039 be2a18bf Phil Davis
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
1040 fe22a89b Ermal
		return ($interfacegw);
1041 f040882c Renato Botelho
	}
1042 fe22a89b Ermal
1043 f040882c Renato Botelho
	return (false);
1044 6dc3a5c2 Ermal Lu?i
}
1045
1046 a2532739 Ermal Lu?i
function get_interface_gateway($interface, &$dynamic = false) {
1047 5a5413bb Seth Mos
	global $config, $g;
1048 6dc3a5c2 Ermal Lu?i
1049 9ba87997 Phil Davis
	if (substr($interface, 0, 4) == '_vip') {
1050 2525ea04 Ermal LUÇI
		$interface = get_configured_carp_interface_list($interface, 'inet', 'iface');
1051 9ba87997 Phil Davis
	}
1052 6dc3a5c2 Ermal Lu?i
1053 89f171b0 Ermal LUÇI
	$gw = NULL;
1054 5a5413bb Seth Mos
	$gwcfg = $config['interfaces'][$interface];
1055
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
1056 9ba87997 Phil Davis
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1057
			if (($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
1058 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
1059 66a96e72 Ermal
				break;
1060
			}
1061 5a5413bb Seth Mos
		}
1062 66a96e72 Ermal
	}
1063 6dc3a5c2 Ermal Lu?i
1064 5a5413bb Seth Mos
	// for dynamic interfaces we handle them through the $interface_router file.
1065 d3c269d3 Ermal
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
1066 5a5413bb Seth Mos
		$realif = get_real_interface($interface);
1067
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
1068 9ba87997 Phil Davis
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
1069 5a5413bb Seth Mos
			$dynamic = true;
1070
		}
1071 9ba87997 Phil Davis
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw")) {
1072 5a5413bb Seth Mos
			$dynamic = "default";
1073 9ba87997 Phil Davis
		}
1074 f040882c Renato Botelho
1075 5a5413bb Seth Mos
	}
1076
1077
	/* return gateway */
1078
	return ($gw);
1079
}
1080
1081
function get_interface_gateway_v6($interface, &$dynamic = false) {
1082
	global $config, $g;
1083 6dc3a5c2 Ermal Lu?i
1084 9ba87997 Phil Davis
	if (substr($interface, 0, 4) == '_vip') {
1085 89f171b0 Ermal LUÇI
		$interface = get_configured_carp_interface_list($interface, 'inet6', 'iface');
1086 9ba87997 Phil Davis
	}
1087 89f171b0 Ermal LUÇI
1088 5a5413bb Seth Mos
	$gw = NULL;
1089
	$gwcfg = $config['interfaces'][$interface];
1090 ed5c640d Seth Mos
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1091 9ba87997 Phil Davis
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1092
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1093 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
1094
				break;
1095
			}
1096
		}
1097
	}
1098
1099
	// for dynamic interfaces we handle them through the $interface_router file.
1100 d3c269d3 Ermal
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1101 9ba87997 Phil Davis
		$realif = get_real_interface($interface);
1102
		if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1103
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1104
			$dynamic = true;
1105
		}
1106
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6")) {
1107
			$dynamic = "default";
1108
		}
1109 5a5413bb Seth Mos
	}
1110
	/* return gateway */
1111
	return ($gw);
1112 6dc3a5c2 Ermal Lu?i
}
1113
1114 318189b6 smos
/* Check a IP address against a gateway IP or name
1115
 * to verify it's address family */
1116 028ff8f8 Phil Davis
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1117 318189b6 smos
	$v4ip = false;
1118
	$v6ip = false;
1119
	$v4gw = false;
1120
	$v6gw = false;
1121
1122 9ba87997 Phil Davis
	if (is_ipaddrv4($ipaddr)) {
1123 318189b6 smos
		$v4ip = true;
1124 9ba87997 Phil Davis
	}
1125
	if (is_ipaddrv6($ipaddr)) {
1126 318189b6 smos
		$v6ip = true;
1127 9ba87997 Phil Davis
	}
1128
	if (is_ipaddrv4($gwname)) {
1129 318189b6 smos
		$v4gw = true;
1130 9ba87997 Phil Davis
	}
1131
	if (is_ipaddrv6($gwname)) {
1132 318189b6 smos
		$v6gw = true;
1133 9ba87997 Phil Davis
	}
1134 318189b6 smos
1135 9ba87997 Phil Davis
	if ($v4ip && $v4gw) {
1136 318189b6 smos
		return true;
1137 9ba87997 Phil Davis
	}
1138
	if ($v6ip && $v6gw) {
1139 318189b6 smos
		return true;
1140 9ba87997 Phil Davis
	}
1141 318189b6 smos
1142
	/* still no match, carry on, lookup gateways */
1143 028ff8f8 Phil Davis
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1144 318189b6 smos
		$v4gw = true;
1145 9ba87997 Phil Davis
	}
1146 028ff8f8 Phil Davis
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1147 318189b6 smos
		$v6gw = true;
1148 9ba87997 Phil Davis
	}
1149 96cd928b smos
1150
	$gw_array = return_gateways_array();
1151 9ba87997 Phil Davis
	if (is_array($gw_array[$gwname])) {
1152
		switch ($gw_array[$gwname]['ipprotocol']) {
1153 96cd928b smos
			case "inet":
1154
				$v4gw = true;
1155
				break;
1156
			case "inet6":
1157
				$v6gw = true;
1158
				break;
1159
		}
1160 748ff86f Seth Mos
	}
1161 318189b6 smos
1162 9ba87997 Phil Davis
	if ($v4ip && $v4gw) {
1163 318189b6 smos
		return true;
1164 9ba87997 Phil Davis
	}
1165
	if ($v6ip && $v6gw) {
1166 318189b6 smos
		return true;
1167 9ba87997 Phil Davis
	}
1168 f040882c Renato Botelho
1169 318189b6 smos
	return false;
1170
}
1171
1172 cdb0df65 smos
/* check if a interface is part of a gateway group */
1173
function interface_gateway_group_member($interface) {
1174
	global $config;
1175 c447a9fe Ermal
1176 9ba87997 Phil Davis
	if (is_array($config['gateways']['gateway_group'])) {
1177 cdb0df65 smos
		$groups = $config['gateways']['gateway_group'];
1178 9ba87997 Phil Davis
	} else {
1179 cdb0df65 smos
		return false;
1180 9ba87997 Phil Davis
	}
1181 cdb0df65 smos
1182 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1183 9ba87997 Phil Davis
	foreach ($groups as $group) {
1184
		if (is_array($group['item'])) {
1185
			foreach ($group['item'] as $item) {
1186 cdb0df65 smos
				$elements = explode("|", $item);
1187
				$gwname = $elements[0];
1188 c447a9fe Ermal
				if ($interface == $gateways_arr[$gwname]['interface']) {
1189
					unset($gateways_arr);
1190 017817c2 smos
					return true;
1191 c447a9fe Ermal
				}
1192 cdb0df65 smos
			}
1193
		}
1194
	}
1195 c447a9fe Ermal
	unset($gateways_arr);
1196
1197 cdb0df65 smos
	return false;
1198
}
1199 318189b6 smos
1200 58b1112f Ermal
function gateway_is_gwgroup_member($name) {
1201
	global $config;
1202
1203 9ba87997 Phil Davis
	if (is_array($config['gateways']['gateway_group'])) {
1204 58b1112f Ermal
		$groups = $config['gateways']['gateway_group'];
1205 9ba87997 Phil Davis
	} else {
1206 58b1112f Ermal
		return false;
1207 9ba87997 Phil Davis
	}
1208 58b1112f Ermal
1209
	$members = array();
1210 9ba87997 Phil Davis
	foreach ($groups as $group) {
1211 58b1112f Ermal
		if (is_array($group['item'])) {
1212 9ba87997 Phil Davis
			foreach ($group['item'] as $item) {
1213 58b1112f Ermal
				$elements = explode("|", $item);
1214
				$gwname = $elements[0];
1215 9ba87997 Phil Davis
				if ($name == $elements[0]) {
1216 58b1112f Ermal
					$members[] = $group['name'];
1217 9ba87997 Phil Davis
				}
1218 58b1112f Ermal
			}
1219
		}
1220
	}
1221
1222
	return $members;
1223
}
1224 69eefb50 Renato Botelho
?>