Project

General

Profile

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