Project

General

Profile

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