Project

General

Profile

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