Project

General

Profile

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