Project

General

Profile

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