Project

General

Profile

Download (37.2 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 06587e2d Renato Botelho
		"loss_interval" => "1000",
42 69eefb50 Renato Botelho
		"time_period" => "25000",
43
		"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 3a335f07 Renato Botelho
	$failed = array();
285 69eefb50 Renato Botelho
	foreach ($gateways_arr as $gateway) {
286 3a335f07 Renato Botelho
		if (!isset($gateway['enable_dpinger'])) {
287
			continue;
288
		}
289
290
		if (start_dpinger($gateway) != 0) {
291
			/*
292
			 * Save process didn't start and try
293
			 * again later
294
			 */
295
			$failed[] = $gateway['name'];
296
		}
297
	}
298
299
	if (!empty($failed)) {
300
		/* 1 second is enough for IPv6 DAD to finish */
301
		sleep(1);
302
		foreach ($gateways_arr as $gateway) {
303
			if (!in_array($gateway['name'], $failed)) {
304
				continue;
305
			}
306
			if (start_dpinger($gateway) != 0) {
307
				log_error("Error starting gateway monitor " .
308
				    "for {$gateway['name']}");
309
			}
310 3c6787ed N0YB
		}
311 69eefb50 Renato Botelho
	}
312 3c6787ed N0YB
313 b42177b9 Renato Botelho
	return;
314 69eefb50 Renato Botelho
}
315 3c6787ed N0YB
316 69eefb50 Renato Botelho
function get_dpinger_status($gwname) {
317
	global $g;
318 3d471a14 Ermal
319 73e3aa21 Renato Botelho
	$running_processes = running_dpinger_processes();
320
321
	if (!isset($running_processes[$gwname])) {
322
		log_error("dpinger: No dpinger session running for gateway {$gwname}");
323
		return false;
324
	}
325
326
	$proc = $running_processes[$gwname];
327
	unset($running_processes);
328 81f19476 Renato Botelho
329 73e3aa21 Renato Botelho
	if (!file_exists($proc['socket'])) {
330
		log_error("dpinger: status socket {$proc['socket']} not found");
331 69eefb50 Renato Botelho
		return false;
332
	}
333 3d471a14 Ermal
334 73e3aa21 Renato Botelho
	$fp = stream_socket_client("unix://{$proc['socket']}", $errno, $errstr, 10);
335 69eefb50 Renato Botelho
	if (!$fp) {
336 73e3aa21 Renato Botelho
		log_error("dpinger: cannot connect to status socket {$proc['socket']} - $errstr ($errno)");
337 69eefb50 Renato Botelho
		return false;
338
	}
339 d55cba63 N0YB
340 69eefb50 Renato Botelho
	$status = '';
341
	while (!feof($fp)) {
342
		$status .= fgets($fp, 1024);
343 cdcea13f Seth Mos
	}
344 69eefb50 Renato Botelho
	fclose($fp);
345
346
	$r = array();
347
	list(
348 73e3aa21 Renato Botelho
	    $r['gwname'],
349 69eefb50 Renato Botelho
	    $r['latency_avg'],
350
	    $r['latency_stddev'],
351 73e3aa21 Renato Botelho
	    $r['loss']
352 69eefb50 Renato Botelho
	) = explode(' ', preg_replace('/\n/', '', $status));
353 cdcea13f Seth Mos
354 73e3aa21 Renato Botelho
	$r['srcip'] = $proc['srcip'];
355
	$r['targetip'] = $proc['targetip'];
356
357 69eefb50 Renato Botelho
	$gateways_arr = return_gateways_array();
358
	unset($gw);
359
	if (isset($gateways_arr[$gwname])) {
360
		$gw = $gateways_arr[$gwname];
361 746f0afb Ermal
	}
362 4f060616 Ermal
363 08e18c83 Renato Botelho
	$r['latency_avg'] = round($r['latency_avg']/1000, 3);
364
	$r['latency_stddev'] = round($r['latency_stddev']/1000, 3);
365
366 69eefb50 Renato Botelho
	$r['status'] = "none";
367
	if (isset($gw) && isset($gw['force_down'])) {
368
		$r['status'] = "force_down";
369
	} else if (isset($gw)) {
370 73e3aa21 Renato Botelho
		$settings = return_dpinger_defaults();
371
372
		$keys = array(
373
		    'latencylow',
374
		    'latencyhigh',
375
		    'losslow',
376
		    'losshigh'
377
		);
378
379
		/* Replace default values by user-defined */
380
		foreach ($keys as $key) {
381
			if (isset($gw[$key]) && is_numeric($gw[$key])) {
382
				$settings[$key] = $gw[$key];
383
			}
384 d8f89cce Renato Botelho
		}
385
386 73e3aa21 Renato Botelho
		if ($r['latency_avg'] > $settings['latencyhigh'] ||
387
		    $r['loss'] > $settings['losshigh']) {
388
			$r['status'] = "down";
389
		} else if ($r['latency_avg'] > $settings['latencylow']) {
390 69eefb50 Renato Botelho
			$r['status'] = "delay";
391 73e3aa21 Renato Botelho
		} else if ($r['loss'] > $settings['losslow']) {
392
			$r['status'] = "loss";
393 69eefb50 Renato Botelho
		}
394
	}
395
396
	return $r;
397 cdcea13f Seth Mos
}
398
399 0aeb97d2 Phil Davis
/* return the status of the dpinger targets as an array */
400 3d471a14 Ermal
function return_gateways_status($byname = false) {
401 ae9618af Ermal
	global $config, $g;
402 cdcea13f Seth Mos
403 69eefb50 Renato Botelho
	$dpinger_gws = running_dpinger_processes();
404 67ee1ec5 Ermal Luçi
	$status = array();
405 69eefb50 Renato Botelho
406
	$gateways_arr = return_gateways_array();
407
408 73e3aa21 Renato Botelho
	foreach ($dpinger_gws as $gwname => $gwdata) {
409 69eefb50 Renato Botelho
		$dpinger_status = get_dpinger_status($gwname);
410
		if ($dpinger_status === false) {
411
			continue;
412
		}
413
414 9ba87997 Phil Davis
		if ($byname == false) {
415 69eefb50 Renato Botelho
			$target = $dpinger_status['targetip'];
416 9ba87997 Phil Davis
		} else {
417 69eefb50 Renato Botelho
			$target = $gwname;
418 9ba87997 Phil Davis
		}
419 47c48e28 smos
420 dea0921d Ermal
		$status[$target] = array();
421 69eefb50 Renato Botelho
		$status[$target]['monitorip'] = $dpinger_status['targetip'];
422
		$status[$target]['srcip'] = $dpinger_status['srcip'];
423
		$status[$target]['name'] = $gwname;
424 0aeb97d2 Phil Davis
		$status[$target]['delay'] = empty($dpinger_status['latency_avg']) ? "0ms" : $dpinger_status['latency_avg'] . "ms";
425 69eefb50 Renato Botelho
		$status[$target]['loss'] = empty($dpinger_status['loss']) ? "0.0%" : round($dpinger_status['loss'], 1) . "%";
426
		$status[$target]['status'] = $dpinger_status['status'];
427 cdcea13f Seth Mos
	}
428 68f291ff Ermal
429 47c48e28 smos
	/* tack on any gateways that have monitoring disabled
430
	 * or are down, which could cause gateway groups to fail */
431 16106d2e smos
	$gateways_arr = return_gateways_array();
432 9ba87997 Phil Davis
	foreach ($gateways_arr as $gwitem) {
433
		if (!isset($gwitem['monitor_disable'])) {
434 fd34d6a9 Ermal
			continue;
435 9ba87997 Phil Davis
		}
436 69eefb50 Renato Botelho
		if (!is_ipaddr($gwitem['monitor'])) {
437 fd34d6a9 Ermal
			$realif = $gwitem['interface'];
438
			$tgtip = get_interface_gateway($realif);
439 9ba87997 Phil Davis
			if (!is_ipaddr($tgtip)) {
440 fd34d6a9 Ermal
				$tgtip = "none";
441 9ba87997 Phil Davis
			}
442 fd34d6a9 Ermal
			$srcip = find_interface_ip($realif);
443
		} else {
444 69eefb50 Renato Botelho
			$tgtip = $gwitem['monitor'];
445 fd34d6a9 Ermal
			$srcip = find_interface_ip($realif);
446
		}
447 9ba87997 Phil Davis
		if ($byname == true) {
448 fd34d6a9 Ermal
			$target = $gwitem['name'];
449 9ba87997 Phil Davis
		} else {
450 fd34d6a9 Ermal
			$target = $tgtip;
451 9ba87997 Phil Davis
		}
452 fd34d6a9 Ermal
453
		/* failsafe for down interfaces */
454 9ba87997 Phil Davis
		if ($target == "none") {
455 fd34d6a9 Ermal
			$target = $gwitem['name'];
456
			$status[$target]['name'] = $gwitem['name'];
457
			$status[$target]['delay'] = "0.0ms";
458
			$status[$target]['loss'] = "100.0%";
459
			$status[$target]['status'] = "down";
460
		} else {
461
			$status[$target]['monitorip'] = $tgtip;
462
			$status[$target]['srcip'] = $srcip;
463
			$status[$target]['name'] = $gwitem['name'];
464
			$status[$target]['delay'] = "0.0ms";
465
			$status[$target]['loss'] = "0.0%";
466
			$status[$target]['status'] = "none";
467 16106d2e smos
		}
468
	}
469 cdcea13f Seth Mos
	return($status);
470 17623ab5 Bill Marquette
}
471
472 2328dcc5 Seth Mos
/* Return all configured gateways on the system */
473 06b8d43c Renato Botelho
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
474 8d3556c2 gnhb
	global $config, $g;
475 7901dff5 Ermal Luçi
476 c66b4242 Seth Mos
	$gateways_arr = array();
477 8d848bdf Phil Davis
	$gateways_arr_temp = array();
478 c66b4242 Seth Mos
479 74c834f1 smos
	$found_defaultv4 = 0;
480
	$found_defaultv6 = 0;
481
482 33e71f10 jim-p
	// Ensure the interface cache is up to date first
483
	$interfaces = get_interface_arr(true);
484 3930a9c0 smos
	$interfaces_v4 = array();
485
	$interfaces_v6 = array();
486
487 23d9f686 Renato Botelho
	$i = -1;
488 3d471a14 Ermal
	/* Process/add all the configured gateways. */
489 ef05ae5f Ermal
	if (is_array($config['gateways']['gateway_item'])) {
490 1500614c Ermal
		foreach ($config['gateways']['gateway_item'] as $gateway) {
491 23d9f686 Renato Botelho
			/* Increment it here to do not skip items */
492
			$i++;
493
494 06b8d43c Renato Botelho
			if (empty($config['interfaces'][$gateway['interface']])) {
495 9ba87997 Phil Davis
				if ($inactive === false) {
496 06b8d43c Renato Botelho
					continue;
497 9ba87997 Phil Davis
				} else {
498 06b8d43c Renato Botelho
					$gateway['inactive'] = true;
499 9ba87997 Phil Davis
				}
500 06b8d43c Renato Botelho
			}
501 3930a9c0 smos
			$wancfg = $config['interfaces'][$gateway['interface']];
502 1500614c Ermal
503
			/* skip disabled interfaces */
504 9ba87997 Phil Davis
			if ($disabled === false && (!isset($wancfg['enable']))) {
505 1500614c Ermal
				continue;
506 9ba87997 Phil Davis
			}
507 c1d36d26 smos
508 3930a9c0 smos
			/* if the gateway is dynamic and we can find the IPv4, Great! */
509 d07bc322 Renato Botelho
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
510 1500614c Ermal
				if ($gateway['ipprotocol'] == "inet") {
511
					/* we know which interfaces is dynamic, this should be made a function */
512 65cfd0ca Renato Botelho
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
513
					/* no IP address found, set to dynamic */
514 9ba87997 Phil Davis
					if (!is_ipaddrv4($gateway['gateway'])) {
515 65cfd0ca Renato Botelho
						$gateway['gateway'] = "dynamic";
516 9ba87997 Phil Davis
					}
517 65cfd0ca Renato Botelho
					$gateway['dynamic'] = true;
518 74c834f1 smos
				}
519 c1d36d26 smos
520 d07bc322 Renato Botelho
				/* if the gateway is dynamic and we can find the IPv6, Great! */
521 8e78c82c Renato Botelho
				else if ($gateway['ipprotocol'] == "inet6") {
522 1500614c Ermal
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
523 65cfd0ca Renato Botelho
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
524 d07bc322 Renato Botelho
					/* no IPv6 address found, set to dynamic */
525 9ba87997 Phil Davis
					if (!is_ipaddrv6($gateway['gateway'])) {
526 d07bc322 Renato Botelho
						$gateway['gateway'] = "dynamic";
527 9ba87997 Phil Davis
					}
528 65cfd0ca Renato Botelho
					$gateway['dynamic'] = true;
529 7671c940 Seth Mos
				}
530 1500614c Ermal
			} else {
531
				/* getting this detection right is hard at this point because we still don't
532
				 * store the address family in the gateway item */
533 9ba87997 Phil Davis
				if (is_ipaddrv4($gateway['gateway'])) {
534 1500614c Ermal
					$gateway['ipprotocol'] = "inet";
535 9ba87997 Phil Davis
				} else if (is_ipaddrv6($gateway['gateway'])) {
536 1500614c Ermal
					$gateway['ipprotocol'] = "inet6";
537 9ba87997 Phil Davis
				}
538 2328dcc5 Seth Mos
			}
539 c1d36d26 smos
540 9ba87997 Phil Davis
			if (isset($gateway['monitor_disable'])) {
541 33c06ef7 Ermal
				$gateway['monitor_disable'] = true;
542 9ba87997 Phil Davis
			} else if (empty($gateway['monitor'])) {
543 2328dcc5 Seth Mos
				$gateway['monitor'] = $gateway['gateway'];
544 9ba87997 Phil Davis
			}
545 3d471a14 Ermal
546 883c53c9 Ermal Lu?i
			$gateway['friendlyiface'] = $gateway['interface'];
547 c1d36d26 smos
548
			/* special treatment for tunnel interfaces */
549 1500614c Ermal
			if ($gateway['ipprotocol'] == "inet6") {
550 33e71f10 jim-p
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
551 1500614c Ermal
				$interfaces_v6[$gateway['friendlyiface']] = $gateway['friendlyiface'];
552
			} else {
553 33e71f10 jim-p
				$gateway['interface'] = get_real_interface($gateway['interface'], "all", false, false);
554 1500614c Ermal
				$interfaces_v4[$gateway['friendlyiface']] = $gateway['friendlyiface'];
555
			}
556 74c834f1 smos
557
			/* entry has a default flag, use it */
558
			if (isset($gateway['defaultgw'])) {
559 1500614c Ermal
				if ($gateway['ipprotocol'] == "inet") {
560 74c834f1 smos
					$gateway['defaultgw'] = true;
561
					$found_defaultv4 = 1;
562 1500614c Ermal
				} else if ($gateway['ipprotocol'] == "inet6") {
563 74c834f1 smos
					$gateway['defaultgw'] = true;
564
					$found_defaultv6 = 1;
565
				}
566
			}
567 3d471a14 Ermal
			/* include the gateway index as the attribute */
568
			$gateway['attribute'] = $i;
569 2328dcc5 Seth Mos
570 8d848bdf Phil Davis
			/* Remember all the gateway names, even ones to be skipped because they are disabled. */
571
			/* Then we can easily know and match them later when attempting to add dynamic gateways to the list. */
572
			$gateways_arr_temp[$gateway['name']] = $gateway;
573
574
			/* skip disabled gateways if the caller has not asked for them to be returned. */
575 9ba87997 Phil Davis
			if (!($disabled === false && isset($gateway['disabled']))) {
576 8d848bdf Phil Davis
				$gateways_arr[$gateway['name']] = $gateway;
577 9ba87997 Phil Davis
			}
578 2328dcc5 Seth Mos
		}
579 c1d36d26 smos
	}
580 1500614c Ermal
	unset($gateway);
581 883c53c9 Ermal Lu?i
582 ef05ae5f Ermal
	/* Loop through all interfaces with a gateway and add it to a array */
583 9ba87997 Phil Davis
	if ($disabled == false) {
584 ef05ae5f Ermal
		$iflist = get_configured_interface_with_descr();
585 9ba87997 Phil Davis
	} else {
586 ef05ae5f Ermal
		$iflist = get_configured_interface_with_descr(false, true);
587 9ba87997 Phil Davis
	}
588 ef05ae5f Ermal
589 c3a0d2a5 Seth Mos
	/* Process/add dynamic v4 gateways. */
590 086cf944 Phil Davis
	foreach ($iflist as $ifname => $friendly) {
591
		if (!interface_has_gateway($ifname)) {
592 883c53c9 Ermal Lu?i
			continue;
593 9ba87997 Phil Davis
		}
594 3d471a14 Ermal
595 9ba87997 Phil Davis
		if (empty($config['interfaces'][$ifname])) {
596 86df2846 jim-p
			continue;
597 9ba87997 Phil Davis
		}
598 86df2846 jim-p
599
		$ifcfg = &$config['interfaces'][$ifname];
600 9ba87997 Phil Davis
		if (!isset($ifcfg['enable'])) {
601 e62fe748 Ermal
			continue;
602 9ba87997 Phil Davis
		}
603 e62fe748 Ermal
604 9ba87997 Phil Davis
		if (!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr'])) {
605 74c834f1 smos
			continue;
606 9ba87997 Phil Davis
		}
607 3930a9c0 smos
608 9ba87997 Phil Davis
		if (isset($interfaces_v4[$ifname])) {
609 3930a9c0 smos
			continue;
610 9ba87997 Phil Davis
		}
611 f040882c Renato Botelho
612 74c834f1 smos
		$ctype = "";
613 9ba87997 Phil Davis
		switch ($ifcfg['ipaddr']) {
614 74c834f1 smos
			case "dhcp":
615
			case "pppoe":
616
			case "pptp":
617 b2ff5d17 smos
			case "ppp":
618 74c834f1 smos
				$ctype = strtoupper($ifcfg['ipaddr']);
619
				break;
620 daac437f jim-p
			default:
621 11fb4543 Chris Buechler
				$tunnelif = substr($ifcfg['if'], 0, 3);
622 6c07db48 Phil Davis
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
623 687ff78c Chris Buechler
					// if current iface is an ovpn server endpoint then check its type, skip tap only
624
					if (substr($ifcfg['if'], 4, 1) == 's') {
625
						$ovpnid = substr($ifcfg['if'], 5);
626
						if (is_array($config['openvpn']['openvpn-server'])) {
627
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
628
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
629 9ba87997 Phil Davis
									if ($ovpnserverconf['dev_mode'] == "tap") {
630 687ff78c Chris Buechler
										continue 3;
631 9ba87997 Phil Davis
									}
632 687ff78c Chris Buechler
								}
633
							}
634
						}
635
					}
636 daac437f jim-p
					$ctype = "VPNv4";
637 9ba87997 Phil Davis
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
638 bac17444 Chris Buechler
					$ctype = "TUNNELv4";
639 9ba87997 Phil Davis
				}
640 daac437f jim-p
				break;
641 74c834f1 smos
		}
642
		$ctype = "_". strtoupper($ctype);
643
644 883c53c9 Ermal Lu?i
		$gateway = array();
645
		$gateway['dynamic'] = false;
646 c3a0d2a5 Seth Mos
		$gateway['ipprotocol'] = "inet";
647 883c53c9 Ermal Lu?i
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
648
		$gateway['interface'] = get_real_interface($ifname);
649
		$gateway['friendlyiface'] = $ifname;
650 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
651 883c53c9 Ermal Lu?i
		$gateway['attribute'] = "system";
652 f040882c Renato Botelho
653 74c834f1 smos
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
654 999111cb Ermal
			$gateway['defaultgw'] = true;
655
			$gateway['dynamic'] = true;
656 74c834f1 smos
			$found_defaultv4 = 1;
657 999111cb Ermal
		}
658 883c53c9 Ermal Lu?i
		/* Loopback dummy for dynamic interfaces without a IP */
659 9ba87997 Phil Davis
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true) {
660 999111cb Ermal
			$gateway['gateway'] = "dynamic";
661 9ba87997 Phil Davis
		}
662 3439b033 Seth Mos
663 8d848bdf Phil Davis
		/* automatically skip known static and dynamic gateways that were previously processed */
664 9ba87997 Phil Davis
		foreach ($gateways_arr_temp as $gateway_item) {
665 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
666 918bdf0d Phil Davis
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
667 9ba87997 Phil Davis
				continue 2;
668
			}
669 883c53c9 Ermal Lu?i
		}
670 c66b4242 Seth Mos
671 9ba87997 Phil Davis
		if (is_ipaddrv4($gateway['gateway'])) {
672 883c53c9 Ermal Lu?i
			$gateway['monitor'] = $gateway['gateway'];
673 9ba87997 Phil Davis
		}
674 c65e1e0d Ermal
675 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
676 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
677
	}
678 1500614c Ermal
	unset($gateway);
679 c3a0d2a5 Seth Mos
680
	/* Process/add dynamic v6 gateways. */
681 086cf944 Phil Davis
	foreach ($iflist as $ifname => $friendly) {
682 0715ad50 jim-p
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
683 9ba87997 Phil Davis
		if (!isset($config['system']['ipv6allow'])) {
684 0715ad50 jim-p
			break;
685 9ba87997 Phil Davis
		}
686 0715ad50 jim-p
687 086cf944 Phil Davis
		if (!interface_has_gatewayv6($ifname)) {
688 c3a0d2a5 Seth Mos
			continue;
689 9ba87997 Phil Davis
		}
690 c3a0d2a5 Seth Mos
691 9ba87997 Phil Davis
		if (empty($config['interfaces'][$ifname])) {
692 c3a0d2a5 Seth Mos
			continue;
693 9ba87997 Phil Davis
		}
694 c3a0d2a5 Seth Mos
695
		$ifcfg = &$config['interfaces'][$ifname];
696 9ba87997 Phil Davis
		if (!isset($ifcfg['enable'])) {
697 74c834f1 smos
			continue;
698 9ba87997 Phil Davis
		}
699 74c834f1 smos
700 9ba87997 Phil Davis
		if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
701 1500614c Ermal
			continue;
702 9ba87997 Phil Davis
		}
703 f040882c Renato Botelho
704 9ba87997 Phil Davis
		if (isset($interfaces_v6[$ifname])) {
705 3930a9c0 smos
			continue;
706 9ba87997 Phil Davis
		}
707 3930a9c0 smos
708 74c834f1 smos
		$ctype = "";
709 9ba87997 Phil Davis
		switch ($ifcfg['ipaddrv6']) {
710 c0b1bc81 smos
			case "slaac":
711 74c834f1 smos
			case "dhcp6":
712
			case "6to4":
713
			case "6rd":
714
				$ctype = strtoupper($ifcfg['ipaddrv6']);
715
				break;
716 daac437f jim-p
			default:
717 bf36dafa Renato Botelho
				$tunnelif = substr($ifcfg['if'], 0, 3);
718 6c07db48 Phil Davis
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
719 687ff78c Chris Buechler
					// if current iface is an ovpn server endpoint then check its type, skip tap only
720
					if (substr($ifcfg['if'], 4, 1) == 's') {
721
						$ovpnid = substr($ifcfg['if'], 5);
722
						if (is_array($config['openvpn']['openvpn-server'])) {
723
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
724
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
725 9ba87997 Phil Davis
									if ($ovpnserverconf['dev_mode'] == "tap") {
726 687ff78c Chris Buechler
										continue 3;
727 9ba87997 Phil Davis
									}
728 687ff78c Chris Buechler
								}
729
							}
730
						}
731
					}
732 daac437f jim-p
					$ctype = "VPNv6";
733 9ba87997 Phil Davis
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
734 c32a6b82 Ermal
					$ctype = "TUNNELv6";
735 9ba87997 Phil Davis
				}
736 daac437f jim-p
				break;
737 74c834f1 smos
		}
738
		$ctype = "_". strtoupper($ctype);
739 c3a0d2a5 Seth Mos
740
		$gateway = array();
741
		$gateway['dynamic'] = false;
742
		$gateway['ipprotocol'] = "inet6";
743
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
744 909de400 Ermal
		$gateway['interface'] = get_real_interface($ifname, "inet6");
745 9ba87997 Phil Davis
		switch ($ifcfg['ipaddrv6']) {
746 d500e296 smos
			case "6rd":
747 909de400 Ermal
			case "6to4":
748 d500e296 smos
				$gateway['dynamic'] = "default";
749
				break;
750
		}
751 c3a0d2a5 Seth Mos
		$gateway['friendlyiface'] = $ifname;
752 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
753 c3a0d2a5 Seth Mos
		$gateway['attribute'] = "system";
754 f040882c Renato Botelho
755 6c07db48 Phil Davis
		if (($gateway['dynamic'] === "default") && ($found_defaultv6 == 0)) {
756 c3a0d2a5 Seth Mos
			$gateway['defaultgw'] = true;
757
			$gateway['dynamic'] = true;
758 74c834f1 smos
			$found_defaultv6 = 1;
759 c3a0d2a5 Seth Mos
		}
760
761
		/* Loopback dummy for dynamic interfaces without a IP */
762 9ba87997 Phil Davis
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true) {
763 d07bc322 Renato Botelho
			$gateway['gateway'] = "dynamic";
764 9ba87997 Phil Davis
		}
765 c3a0d2a5 Seth Mos
766 8d848bdf Phil Davis
		/* automatically skip known static and dynamic gateways that were previously processed */
767 9ba87997 Phil Davis
		foreach ($gateways_arr_temp as $gateway_item) {
768 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
769 918bdf0d Phil Davis
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
770 9ba87997 Phil Davis
				continue 2;
771
			}
772 c3a0d2a5 Seth Mos
		}
773
774 9ba87997 Phil Davis
		if (is_ipaddrv6($gateway['gateway'])) {
775 c3a0d2a5 Seth Mos
			$gateway['monitor'] = $gateway['gateway'];
776 9ba87997 Phil Davis
		}
777 c3a0d2a5 Seth Mos
778 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
779 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
780 c66b4242 Seth Mos
	}
781 1500614c Ermal
	unset($gateway);
782 6fdea6a2 smos
783 08c3810c Renato Botelho
	/* FIXME: Should this be enabled.
784
	 * Some interface like wan might be default but have no info recorded
785
	 * the config. */
786
	/* this is a fallback if all else fails and we want to get packets out @smos */
787
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
788
		foreach ($gateways_arr as &$gateway) {
789
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
790
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
791
					$gateway['defaultgw'] = true;
792
					$found_defaultv4 = 1;
793
				}
794
			}
795 6704590b Ermal
			else if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
796 08c3810c Renato Botelho
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
797
					$gateway['defaultgw'] = true;
798
					$found_defaultv6 = 1;
799
				}
800
			}
801
		}
802
	}
803
804 9ba87997 Phil Davis
	if ($localhost === true) {
805 6fdea6a2 smos
		/* attach localhost for Null routes */
806
		$gwlo4 = array();
807
		$gwlo4['name'] = "Null4";
808
		$gwlo4['interface'] = "lo0";
809
		$gwlo4['ipprotocol'] = "inet";
810
		$gwlo4['gateway'] = "127.0.0.1";
811
		$gwlo6 = array();
812
		$gwlo6['name'] = "Null6";
813
		$gwlo6['interface'] = "lo0";
814
		$gwlo6['ipprotocol'] = "inet6";
815
		$gwlo6['gateway'] = "::1";
816
		$gateways_arr['Null4'] = $gwlo4;
817
		$gateways_arr['Null6'] = $gwlo6;
818
	}
819 c66b4242 Seth Mos
	return($gateways_arr);
820
}
821
822 fd3515f2 jim-p
function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) {
823
	global $config, $g;
824
	/*
825
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
826
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
827
	 */
828 894a0159 Ermal
	$upgw = '';
829
	$dfltgwname = '';
830 fd3515f2 jim-p
	$dfltgwdown = false;
831
	$dfltgwfound = false;
832
	foreach ($gateways_arr as $gwname => $gwsttng) {
833
		if (($gwsttng['ipprotocol'] == $ipprotocol) && isset($gwsttng['defaultgw'])) {
834
			$dfltgwfound = true;
835
			$dfltgwname = $gwname;
836 23cb4055 Chris Buechler
			if (!isset($gwsttng['monitor_disable']) && $gateways_status[$gwname]['status'] != "none") {
837 fd3515f2 jim-p
				$dfltgwdown = true;
838 9ba87997 Phil Davis
			}
839 fd3515f2 jim-p
		}
840
		/* Keep a record of the last up gateway */
841
		/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
842 23cb4055 Chris Buechler
		if (empty($upgw) && ($gwsttng['ipprotocol'] == $ipprotocol) && (isset($gwsttng['monitor_disable']) || $gateways_status[$gwname]['status'] == "none") && $gwsttng[$gwname]['friendlyiface'] != "lan") {
843 fd3515f2 jim-p
			$upgw = $gwname;
844 9ba87997 Phil Davis
		}
845
		if ($dfltgwdown == true && !empty($upgw)) {
846 fd3515f2 jim-p
			break;
847 9ba87997 Phil Davis
		}
848 fd3515f2 jim-p
	}
849
	if ($dfltgwfound == false) {
850
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
851 9ba87997 Phil Davis
		if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down")) {
852 fd3515f2 jim-p
			$dfltgwdown = true;
853 9ba87997 Phil Davis
		}
854 fd3515f2 jim-p
	}
855
	if ($dfltgwdown == true && !empty($upgw)) {
856 9ba87997 Phil Davis
		if ($gateways_arr[$upgw]['gateway'] == "dynamic") {
857 fd3515f2 jim-p
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
858 9ba87997 Phil Davis
		}
859 fd3515f2 jim-p
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
860
			log_error("Default gateway down setting {$upgw} as default!");
861 9ba87997 Phil Davis
			if (is_ipaddrv6($gateways_arr[$upgw]['gateway'])) {
862 fd3515f2 jim-p
				$inetfamily = "-inet6";
863
			} else {
864
				$inetfamily = "-inet";
865
			}
866
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
867
		}
868 fea0b652 Ermal LUÇI
	} else if (!empty($dfltgwname)) {
869 96fcabaa Renato Botelho
		$defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n");
870 9ba87997 Phil Davis
		if ($ipprotocol == 'inet6' && !is_ipaddrv6($gateways_arr[$dfltgwname]['gateway'])) {
871 894a0159 Ermal
			return;
872 9ba87997 Phil Davis
		}
873
		if ($ipprotocol == 'inet' && !is_ipaddrv4($gateways_arr[$dfltgwname]['gateway'])) {
874 894a0159 Ermal
			return;
875 9ba87997 Phil Davis
		}
876
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway']) {
877 894a0159 Ermal
			mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}");
878 9ba87997 Phil Davis
		}
879 fd3515f2 jim-p
	}
880
}
881
882 3d471a14 Ermal
/*
883
 * Return an array with all gateway groups with name as key
884 fd8eeda5 Seth Mos
 * All gateway groups will be processed before returning the array.
885 3d471a14 Ermal
 */
886 fd8eeda5 Seth Mos
function return_gateway_groups_array() {
887 962625aa Ermal
	global $config, $g;
888 fd8eeda5 Seth Mos
889
	/* fetch the current gateways status */
890 3d471a14 Ermal
	$gateways_status = return_gateways_status(true);
891 fd8eeda5 Seth Mos
	$gateways_arr = return_gateways_array();
892
	$gateway_groups_array = array();
893
894 7af360ce Ermal
	if (isset($config['system']['gw_switch_default'])) {
895 fd3515f2 jim-p
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
896
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
897 ee7f1647 Ermal
	}
898 fd8eeda5 Seth Mos
	if (is_array($config['gateways']['gateway_group'])) {
899 1500614c Ermal
		$carplist = get_configured_carp_interface_list();
900
		foreach ($config['gateways']['gateway_group'] as $group) {
901 5aa68a55 Renato Botelho
			/* create array with group gateways members separated by tier */
902 fd8eeda5 Seth Mos
			$tiers = array();
903 3d471a14 Ermal
			$backupplan = array();
904 1500614c Ermal
			$gwvip_arr = array();
905
			foreach ($group['item'] as $item) {
906 dea0921d Ermal
				list($gwname, $tier, $vipname) = explode("|", $item);
907 1500614c Ermal
908
				if (is_ipaddr($carplist[$vipname])) {
909 9ba87997 Phil Davis
					if (!is_array($gwvip_arr[$group['name']])) {
910 1500614c Ermal
						$gwvip_arr[$group['name']] = array();
911 9ba87997 Phil Davis
					}
912 ab1112da smos
					$gwvip_arr[$group['name']][$gwname] = $vipname;
913 1500614c Ermal
				}
914 3d471a14 Ermal
915
				/* Do it here rather than reiterating again the group in case no member is up. */
916 9ba87997 Phil Davis
				if (!is_array($backupplan[$tier])) {
917 dea0921d Ermal
					$backupplan[$tier] = array();
918 9ba87997 Phil Davis
				}
919 d8bf779b Ermal
				$backupplan[$tier][] = $gwname;
920 3d471a14 Ermal
921 fd8eeda5 Seth Mos
				/* check if the gateway is available before adding it to the array */
922 e0ba24f7 smos
				if (is_array($gateways_status[$gwname])) {
923 54b78cc1 Ermal
					$status = $gateways_status[$gwname];
924 3d471a14 Ermal
					$gwdown = false;
925 9af4b31b Ermal
					if (stristr($status['status'], "down")) {
926 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s is down, omitting from routing group {$group['name']}"), $gwname);
927 3d471a14 Ermal
						$gwdown = true;
928
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
929
						/* packet loss */
930 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s has packet loss, omitting from routing group {$group['name']}"), $gwname);
931 3d471a14 Ermal
						$gwdown = true;
932
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
933
						/* high latency */
934 b22f436a Chris Buechler
						$msg = sprintf(gettext("MONITOR: %s has high latency, omitting from routing group {$group['name']}"), $gwname);
935 3d471a14 Ermal
						$gwdown = true;
936
					}
937
					if ($gwdown == true) {
938 9f1d61d3 Scott Ullrich
						log_error($msg);
939
						notify_via_growl($msg);
940 10c3d4c0 Scott Ullrich
						notify_via_smtp($msg);
941 e0ba24f7 smos
					} else {
942 857ce5f3 Seth Mos
						/* Online add member */
943 9ba87997 Phil Davis
						if (!is_array($tiers[$tier])) {
944 dea0921d Ermal
							$tiers[$tier] = array();
945 9ba87997 Phil Davis
						}
946 857ce5f3 Seth Mos
						$tiers[$tier][] = $gwname;
947 e0ba24f7 smos
					}
948 9ba87997 Phil Davis
				} else if (isset($gateways_arr[$gwname]['monitor_disable'])) {
949 33c06ef7 Ermal
					$tiers[$tier][] = $gwname;
950 9ba87997 Phil Davis
				}
951 fd8eeda5 Seth Mos
			}
952
			$tiers_count = count($tiers);
953 1500614c Ermal
			if ($tiers_count == 0) {
954 fd8eeda5 Seth Mos
				/* Oh dear, we have no members! Engage Plan B */
955 285ef132 Ermal LUÇI
				if (!platform_booting()) {
956 50006cca PiBa-NL
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
957 9132ae35 Ermal
					log_error($msg);
958
					notify_via_growl($msg);
959 72b4a1e8 jim-p
					//notify_via_smtp($msg);
960 9132ae35 Ermal
				}
961 3d471a14 Ermal
				$tiers = $backupplan;
962 fd8eeda5 Seth Mos
			}
963 09ae0c17 Seth Mos
			/* sort the tiers array by the tier key */
964
			ksort($tiers);
965 3d471a14 Ermal
966 fd8eeda5 Seth Mos
			/* we do not really foreach the tiers as we stop after the first tier */
967 1500614c Ermal
			foreach ($tiers as $tieridx => $tier) {
968 fd8eeda5 Seth Mos
				/* process all gateways in this tier */
969 1500614c Ermal
				foreach ($tier as $member) {
970 fd8eeda5 Seth Mos
					/* determine interface gateway */
971 5f53260a Ermal
					if (isset($gateways_arr[$member])) {
972
						$gateway = $gateways_arr[$member];
973
						$int = $gateway['interface'];
974
						$gatewayip = "";
975 9ba87997 Phil Davis
						if (is_ipaddr($gateway['gateway'])) {
976 5f53260a Ermal
							$gatewayip = $gateway['gateway'];
977 9ba87997 Phil Davis
						} else if (!empty($int)) {
978 5f53260a Ermal
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
979 9ba87997 Phil Davis
						}
980 f040882c Renato Botelho
981 f60003fa Phil Davis
						if (!empty($int)) {
982 44b054ce smos
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
983 f60003fa Phil Davis
							if (is_ipaddr($gatewayip)) {
984
								$groupmember = array();
985 6c07db48 Phil Davis
								$groupmember['int'] = $int;
986
								$groupmember['gwip'] = $gatewayip;
987
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
988 9ba87997 Phil Davis
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member])) {
989 f60003fa Phil Davis
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
990 9ba87997 Phil Davis
								}
991 f60003fa Phil Davis
								$gateway_groups_array[$group['name']][] = $groupmember;
992
							}
993 3d471a14 Ermal
						}
994 fd8eeda5 Seth Mos
					}
995
				}
996
				/* we should have the 1st available tier now, exit stage left */
997 9ba87997 Phil Davis
				if (count($gateway_groups_array[$group['name']]) > 0) {
998 47c48e28 smos
					break;
999 9ba87997 Phil Davis
				} else {
1000 1500614c Ermal
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
1001 9ba87997 Phil Davis
				}
1002 fd8eeda5 Seth Mos
			}
1003
		}
1004
	}
1005 1500614c Ermal
1006 fe22a89b Ermal
	return ($gateway_groups_array);
1007 fd8eeda5 Seth Mos
}
1008
1009 2468ae76 Scott Ullrich
/* Update DHCP WAN Interface ip address in gateway group item */
1010
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
1011
	global $config, $g;
1012 9ba87997 Phil Davis
	foreach ($config['gateways']['gateway_item'] as & $gw) {
1013
		if ($gw['interface'] == $interface) {
1014 2468ae76 Scott Ullrich
			$current_gw = get_interface_gateway($interface);
1015 9ba87997 Phil Davis
			if ($gw['gateway'] <> $current_gw) {
1016 2468ae76 Scott Ullrich
				$gw['gateway'] = $current_gw;
1017
				$changed = true;
1018
			}
1019
		}
1020
	}
1021 9ba87997 Phil Davis
	if ($changed && $current_gw) {
1022 addc0439 Renato Botelho
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
1023 9ba87997 Phil Davis
	}
1024 2468ae76 Scott Ullrich
}
1025 fd8eeda5 Seth Mos
1026 028ff8f8 Phil Davis
function lookup_gateway_ip_by_name($name, $disabled = false) {
1027 fe22a89b Ermal
1028 028ff8f8 Phil Davis
	$gateways_arr = return_gateways_array($disabled, true);
1029 f040882c Renato Botelho
	foreach ($gateways_arr as $gname => $gw) {
1030 9ba87997 Phil Davis
		if ($gw['name'] === $name || $gname === $name) {
1031 f040882c Renato Botelho
			return $gw['gateway'];
1032 9ba87997 Phil Davis
		}
1033 f040882c Renato Botelho
	}
1034 66a96e72 Ermal
1035
	return false;
1036 6dc3a5c2 Ermal Lu?i
}
1037
1038
function lookup_gateway_monitor_ip_by_name($name) {
1039 fe22a89b Ermal
1040 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1041 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
1042
		$gateway = $gateways_arr[$name];
1043 9ba87997 Phil Davis
		if (!is_ipaddr($gateway['monitor'])) {
1044 68f291ff Ermal
			return $gateway['gateway'];
1045 9ba87997 Phil Davis
		}
1046 6dc3a5c2 Ermal Lu?i
1047 9fd19334 gnhb
		return $gateway['monitor'];
1048 f040882c Renato Botelho
	}
1049 fe22a89b Ermal
1050 f040882c Renato Botelho
	return (false);
1051 6dc3a5c2 Ermal Lu?i
}
1052
1053
function lookup_gateway_interface_by_name($name) {
1054
1055 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1056 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
1057 be2a18bf Phil Davis
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
1058 fe22a89b Ermal
		return ($interfacegw);
1059 f040882c Renato Botelho
	}
1060 fe22a89b Ermal
1061 f040882c Renato Botelho
	return (false);
1062 6dc3a5c2 Ermal Lu?i
}
1063
1064 a2532739 Ermal Lu?i
function get_interface_gateway($interface, &$dynamic = false) {
1065 5a5413bb Seth Mos
	global $config, $g;
1066 6dc3a5c2 Ermal Lu?i
1067 9ba87997 Phil Davis
	if (substr($interface, 0, 4) == '_vip') {
1068 2525ea04 Ermal LUÇI
		$interface = get_configured_carp_interface_list($interface, 'inet', 'iface');
1069 9ba87997 Phil Davis
	}
1070 6dc3a5c2 Ermal Lu?i
1071 89f171b0 Ermal LUÇI
	$gw = NULL;
1072 5a5413bb Seth Mos
	$gwcfg = $config['interfaces'][$interface];
1073
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
1074 9ba87997 Phil Davis
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1075
			if (($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
1076 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
1077 66a96e72 Ermal
				break;
1078
			}
1079 5a5413bb Seth Mos
		}
1080 66a96e72 Ermal
	}
1081 6dc3a5c2 Ermal Lu?i
1082 5a5413bb Seth Mos
	// for dynamic interfaces we handle them through the $interface_router file.
1083 d3c269d3 Ermal
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
1084 5a5413bb Seth Mos
		$realif = get_real_interface($interface);
1085
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
1086 9ba87997 Phil Davis
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
1087 5a5413bb Seth Mos
			$dynamic = true;
1088
		}
1089 9ba87997 Phil Davis
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw")) {
1090 5a5413bb Seth Mos
			$dynamic = "default";
1091 9ba87997 Phil Davis
		}
1092 f040882c Renato Botelho
1093 5a5413bb Seth Mos
	}
1094
1095
	/* return gateway */
1096
	return ($gw);
1097
}
1098
1099
function get_interface_gateway_v6($interface, &$dynamic = false) {
1100
	global $config, $g;
1101 6dc3a5c2 Ermal Lu?i
1102 9ba87997 Phil Davis
	if (substr($interface, 0, 4) == '_vip') {
1103 89f171b0 Ermal LUÇI
		$interface = get_configured_carp_interface_list($interface, 'inet6', 'iface');
1104 9ba87997 Phil Davis
	}
1105 89f171b0 Ermal LUÇI
1106 5a5413bb Seth Mos
	$gw = NULL;
1107
	$gwcfg = $config['interfaces'][$interface];
1108 ed5c640d Seth Mos
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1109 9ba87997 Phil Davis
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1110
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1111 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
1112
				break;
1113
			}
1114
		}
1115
	}
1116
1117
	// for dynamic interfaces we handle them through the $interface_router file.
1118 d3c269d3 Ermal
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1119 9ba87997 Phil Davis
		$realif = get_real_interface($interface);
1120
		if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1121
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1122
			$dynamic = true;
1123
		}
1124
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6")) {
1125
			$dynamic = "default";
1126
		}
1127 5a5413bb Seth Mos
	}
1128
	/* return gateway */
1129
	return ($gw);
1130 6dc3a5c2 Ermal Lu?i
}
1131
1132 318189b6 smos
/* Check a IP address against a gateway IP or name
1133
 * to verify it's address family */
1134 028ff8f8 Phil Davis
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1135 318189b6 smos
	$v4ip = false;
1136
	$v6ip = false;
1137
	$v4gw = false;
1138
	$v6gw = false;
1139
1140 9ba87997 Phil Davis
	if (is_ipaddrv4($ipaddr)) {
1141 318189b6 smos
		$v4ip = true;
1142 9ba87997 Phil Davis
	}
1143
	if (is_ipaddrv6($ipaddr)) {
1144 318189b6 smos
		$v6ip = true;
1145 9ba87997 Phil Davis
	}
1146
	if (is_ipaddrv4($gwname)) {
1147 318189b6 smos
		$v4gw = true;
1148 9ba87997 Phil Davis
	}
1149
	if (is_ipaddrv6($gwname)) {
1150 318189b6 smos
		$v6gw = true;
1151 9ba87997 Phil Davis
	}
1152 318189b6 smos
1153 9ba87997 Phil Davis
	if ($v4ip && $v4gw) {
1154 318189b6 smos
		return true;
1155 9ba87997 Phil Davis
	}
1156
	if ($v6ip && $v6gw) {
1157 318189b6 smos
		return true;
1158 9ba87997 Phil Davis
	}
1159 318189b6 smos
1160
	/* still no match, carry on, lookup gateways */
1161 028ff8f8 Phil Davis
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1162 318189b6 smos
		$v4gw = true;
1163 9ba87997 Phil Davis
	}
1164 028ff8f8 Phil Davis
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1165 318189b6 smos
		$v6gw = true;
1166 9ba87997 Phil Davis
	}
1167 96cd928b smos
1168
	$gw_array = return_gateways_array();
1169 9ba87997 Phil Davis
	if (is_array($gw_array[$gwname])) {
1170
		switch ($gw_array[$gwname]['ipprotocol']) {
1171 96cd928b smos
			case "inet":
1172
				$v4gw = true;
1173
				break;
1174
			case "inet6":
1175
				$v6gw = true;
1176
				break;
1177
		}
1178 748ff86f Seth Mos
	}
1179 318189b6 smos
1180 9ba87997 Phil Davis
	if ($v4ip && $v4gw) {
1181 318189b6 smos
		return true;
1182 9ba87997 Phil Davis
	}
1183
	if ($v6ip && $v6gw) {
1184 318189b6 smos
		return true;
1185 9ba87997 Phil Davis
	}
1186 f040882c Renato Botelho
1187 318189b6 smos
	return false;
1188
}
1189
1190 cdb0df65 smos
/* check if a interface is part of a gateway group */
1191
function interface_gateway_group_member($interface) {
1192
	global $config;
1193 c447a9fe Ermal
1194 9ba87997 Phil Davis
	if (is_array($config['gateways']['gateway_group'])) {
1195 cdb0df65 smos
		$groups = $config['gateways']['gateway_group'];
1196 9ba87997 Phil Davis
	} else {
1197 cdb0df65 smos
		return false;
1198 9ba87997 Phil Davis
	}
1199 cdb0df65 smos
1200 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1201 9ba87997 Phil Davis
	foreach ($groups as $group) {
1202
		if (is_array($group['item'])) {
1203
			foreach ($group['item'] as $item) {
1204 cdb0df65 smos
				$elements = explode("|", $item);
1205
				$gwname = $elements[0];
1206 c447a9fe Ermal
				if ($interface == $gateways_arr[$gwname]['interface']) {
1207
					unset($gateways_arr);
1208 017817c2 smos
					return true;
1209 c447a9fe Ermal
				}
1210 cdb0df65 smos
			}
1211
		}
1212
	}
1213 c447a9fe Ermal
	unset($gateways_arr);
1214
1215 cdb0df65 smos
	return false;
1216
}
1217 318189b6 smos
1218 58b1112f Ermal
function gateway_is_gwgroup_member($name) {
1219
	global $config;
1220
1221 9ba87997 Phil Davis
	if (is_array($config['gateways']['gateway_group'])) {
1222 58b1112f Ermal
		$groups = $config['gateways']['gateway_group'];
1223 9ba87997 Phil Davis
	} else {
1224 58b1112f Ermal
		return false;
1225 9ba87997 Phil Davis
	}
1226 58b1112f Ermal
1227
	$members = array();
1228 9ba87997 Phil Davis
	foreach ($groups as $group) {
1229 58b1112f Ermal
		if (is_array($group['item'])) {
1230 9ba87997 Phil Davis
			foreach ($group['item'] as $item) {
1231 58b1112f Ermal
				$elements = explode("|", $item);
1232
				$gwname = $elements[0];
1233 9ba87997 Phil Davis
				if ($name == $elements[0]) {
1234 58b1112f Ermal
					$members[] = $group['name'];
1235 9ba87997 Phil Davis
				}
1236 58b1112f Ermal
			}
1237
		}
1238
	}
1239
1240
	return $members;
1241
}
1242 69eefb50 Renato Botelho
?>