Project

General

Profile

Download (36.2 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 c822154c jim-p
				if (substr($ifcfg['if'], 0, 4) ==  "ovpn")
559 daac437f jim-p
					$ctype = "VPNv4";
560
				break;
561 74c834f1 smos
		}
562
		$ctype = "_". strtoupper($ctype);
563
564 883c53c9 Ermal Lu?i
		$gateway = array();
565
		$gateway['dynamic'] = false;
566 c3a0d2a5 Seth Mos
		$gateway['ipprotocol'] = "inet";
567 883c53c9 Ermal Lu?i
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
568
		$gateway['interface'] = get_real_interface($ifname);
569
		$gateway['friendlyiface'] = $ifname;
570 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
571 883c53c9 Ermal Lu?i
		$gateway['attribute'] = "system";
572 f040882c Renato Botelho
573 74c834f1 smos
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
574 999111cb Ermal
			$gateway['defaultgw'] = true;
575
			$gateway['dynamic'] = true;
576 74c834f1 smos
			$found_defaultv4 = 1;
577 999111cb Ermal
		}
578 883c53c9 Ermal Lu?i
		/* Loopback dummy for dynamic interfaces without a IP */
579 c3a0d2a5 Seth Mos
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true)
580 999111cb Ermal
			$gateway['gateway'] = "dynamic";
581 3439b033 Seth Mos
582 883c53c9 Ermal Lu?i
		/* automatically skip known static and dynamic gateways we have a array entry for */
583
		foreach($gateways_arr as $gateway_item) {
584 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
585
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
586 7bed8222 Ermal
					continue 2;
587 883c53c9 Ermal Lu?i
		}
588 c66b4242 Seth Mos
589 c3a0d2a5 Seth Mos
		if (is_ipaddrv4($gateway['gateway']))
590 883c53c9 Ermal Lu?i
			$gateway['monitor'] = $gateway['gateway'];
591 c65e1e0d Ermal
592 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
593 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
594
	}
595 1500614c Ermal
	unset($gateway);
596 c3a0d2a5 Seth Mos
597
	/* Process/add dynamic v6 gateways. */
598
	foreach($iflist as $ifname => $friendly ) {
599 0715ad50 jim-p
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
600
		if (!isset($config['system']['ipv6allow']))
601
			break;
602
603 67102344 smos
		if(! interface_has_gatewayv6($ifname))
604 c3a0d2a5 Seth Mos
			continue;
605
606
		if (empty($config['interfaces'][$ifname]))
607
			continue;
608
609
		$ifcfg = &$config['interfaces'][$ifname];
610 74c834f1 smos
		if(!isset($ifcfg['enable']))
611
			continue;
612
613 1500614c Ermal
		if(!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
614
			continue;
615 f040882c Renato Botelho
616 1500614c Ermal
		if(isset($interfaces_v6[$ifname]))
617 3930a9c0 smos
			continue;
618
619 74c834f1 smos
		$ctype = "";
620
		switch($ifcfg['ipaddrv6']) {
621 c0b1bc81 smos
			case "slaac":
622 74c834f1 smos
			case "dhcp6":
623
			case "6to4":
624
			case "6rd":
625
				$ctype = strtoupper($ifcfg['ipaddrv6']);
626
				break;
627 daac437f jim-p
			default:
628 bf36dafa Renato Botelho
				$tunnelif = substr($ifcfg['if'], 0, 3);
629 c822154c jim-p
				if (substr($ifcfg['if'], 0, 4) ==  "ovpn")
630 daac437f jim-p
					$ctype = "VPNv6";
631 b31247af Ermal
				else if ($tunnelif == "gif" || $tunnelif == "gre")
632 c32a6b82 Ermal
					$ctype = "TUNNELv6";
633 daac437f jim-p
				break;
634 74c834f1 smos
		}
635
		$ctype = "_". strtoupper($ctype);
636 c3a0d2a5 Seth Mos
637
		$gateway = array();
638
		$gateway['dynamic'] = false;
639
		$gateway['ipprotocol'] = "inet6";
640
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
641 909de400 Ermal
		$gateway['interface'] = get_real_interface($ifname, "inet6");
642 d500e296 smos
		switch($ifcfg['ipaddrv6']) {
643
			case "6rd":
644 909de400 Ermal
			case "6to4":
645 d500e296 smos
				$gateway['dynamic'] = "default";
646
				break;
647
		}
648 c3a0d2a5 Seth Mos
		$gateway['friendlyiface'] = $ifname;
649 74c834f1 smos
		$gateway['name'] = "{$friendly}{$ctype}";
650 c3a0d2a5 Seth Mos
		$gateway['attribute'] = "system";
651 f040882c Renato Botelho
652 74c834f1 smos
		if (($gateway['dynamic'] === "default")  && ($found_defaultv6 == 0)) {
653 c3a0d2a5 Seth Mos
			$gateway['defaultgw'] = true;
654
			$gateway['dynamic'] = true;
655 74c834f1 smos
			$found_defaultv6 = 1;
656 c3a0d2a5 Seth Mos
		}
657
658
		/* Loopback dummy for dynamic interfaces without a IP */
659
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true)
660 d07bc322 Renato Botelho
			$gateway['gateway'] = "dynamic";
661 c3a0d2a5 Seth Mos
662
		/* automatically skip known static and dynamic gateways we have a array entry for */
663
		foreach($gateways_arr as $gateway_item) {
664
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
665
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
666
					continue 2;
667
		}
668
669
		if (is_ipaddrv6($gateway['gateway']))
670
			$gateway['monitor'] = $gateway['gateway'];
671
672 74c834f1 smos
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
673 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
674 c66b4242 Seth Mos
	}
675 1500614c Ermal
	unset($gateway);
676 6fdea6a2 smos
677 08c3810c Renato Botelho
	/* FIXME: Should this be enabled.
678
	 * Some interface like wan might be default but have no info recorded
679
	 * the config. */
680
	/* this is a fallback if all else fails and we want to get packets out @smos */
681
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
682
		foreach ($gateways_arr as &$gateway) {
683
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
684
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
685
					$gateway['defaultgw'] = true;
686
					$found_defaultv4 = 1;
687
				}
688
			}
689
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
690
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
691
					$gateway['defaultgw'] = true;
692
					$found_defaultv6 = 1;
693
				}
694
			}
695
		}
696
	}
697
698 6fdea6a2 smos
	if($localhost === true) {
699
		/* attach localhost for Null routes */
700
		$gwlo4 = array();
701
		$gwlo4['name'] = "Null4";
702
		$gwlo4['interface'] = "lo0";
703
		$gwlo4['ipprotocol'] = "inet";
704
		$gwlo4['gateway'] = "127.0.0.1";
705
		$gwlo6 = array();
706
		$gwlo6['name'] = "Null6";
707
		$gwlo6['interface'] = "lo0";
708
		$gwlo6['ipprotocol'] = "inet6";
709
		$gwlo6['gateway'] = "::1";
710
		$gateways_arr['Null4'] = $gwlo4;
711
		$gateways_arr['Null6'] = $gwlo6;
712
	}
713 c66b4242 Seth Mos
	return($gateways_arr);
714
}
715
716 fd3515f2 jim-p
function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) {
717
	global $config, $g;
718
	/*
719
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
720
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
721
	 */
722
	$upgw = "";
723
	$dfltgwdown = false;
724
	$dfltgwfound = false;
725
	foreach ($gateways_arr as $gwname => $gwsttng) {
726
		if (($gwsttng['ipprotocol'] == $ipprotocol) && isset($gwsttng['defaultgw'])) {
727
			$dfltgwfound = true;
728
			$dfltgwname = $gwname;
729
			if (!isset($gwsttng['monitor_disable']) && stristr($gateways_status[$gwname]['status'], "down"))
730
				$dfltgwdown = true;
731
		}
732
		/* Keep a record of the last up gateway */
733
		/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
734
		if (empty($upgw) && ($gwsttng['ipprotocol'] == $ipprotocol) && (isset($gwsttng['monitor_disable']) || !stristr($gateways_status[$gwname]['status'], "down")) && $gwsttng[$gwname]['friendlyiface'] != "lan")
735
			$upgw = $gwname;
736
		if ($dfltgwdown == true && !empty($upgw))
737
			break;
738
	}
739
	if ($dfltgwfound == false) {
740
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
741
		if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down"))
742
			$dfltgwdown = true;
743
	}
744
	if ($dfltgwdown == true && !empty($upgw)) {
745 d07bc322 Renato Botelho
		if ($gateways_arr[$upgw]['gateway'] == "dynamic")
746 fd3515f2 jim-p
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
747
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
748
			log_error("Default gateway down setting {$upgw} as default!");
749
			if(is_ipaddrv6($gateways_arr[$upgw]['gateway'])) {
750
				$inetfamily = "-inet6";
751
			} else {
752
				$inetfamily = "-inet";
753
			}
754
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
755
		}
756
	} else {
757
		$defaultgw = trim(`/sbin/route -n get -{$ipprotocol} default | /usr/bin/grep gateway | /usr/bin/sed 's/gateway://g'`, " \n");
758
		if(is_ipaddrv6($gateways_arr[$dfltgwname]['gateway'])) {
759
			$inetfamily = "-inet6";
760
		} else {
761
			$inetfamily = "-inet";
762
		}
763
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway'])
764
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$dfltgwname]['gateway']}");
765
	}
766
}
767
768 3d471a14 Ermal
/*
769
 * Return an array with all gateway groups with name as key
770 fd8eeda5 Seth Mos
 * All gateway groups will be processed before returning the array.
771 3d471a14 Ermal
 */
772 fd8eeda5 Seth Mos
function return_gateway_groups_array() {
773 962625aa Ermal
	global $config, $g;
774 fd8eeda5 Seth Mos
775
	/* fetch the current gateways status */
776 3d471a14 Ermal
	$gateways_status = return_gateways_status(true);
777 fd8eeda5 Seth Mos
	$gateways_arr = return_gateways_array();
778
	$gateway_groups_array = array();
779
780 7af360ce Ermal
	if (isset($config['system']['gw_switch_default'])) {
781 fd3515f2 jim-p
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
782
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
783 ee7f1647 Ermal
	}
784 fd8eeda5 Seth Mos
	if (is_array($config['gateways']['gateway_group'])) {
785 1500614c Ermal
		$carplist = get_configured_carp_interface_list();
786
		foreach ($config['gateways']['gateway_group'] as $group) {
787 5aa68a55 Renato Botelho
			/* create array with group gateways members separated by tier */
788 fd8eeda5 Seth Mos
			$tiers = array();
789 3d471a14 Ermal
			$backupplan = array();
790 1500614c Ermal
			$gwvip_arr = array();
791
			foreach ($group['item'] as $item) {
792 dea0921d Ermal
				list($gwname, $tier, $vipname) = explode("|", $item);
793 1500614c Ermal
794
				if (is_ipaddr($carplist[$vipname])) {
795 22234bbb Renato Botelho
					if (!is_array($gwvip_arr[$group['name']]))
796 1500614c Ermal
						$gwvip_arr[$group['name']] = array();
797 ab1112da smos
					$gwvip_arr[$group['name']][$gwname] = $vipname;
798 1500614c Ermal
				}
799 3d471a14 Ermal
800
				/* Do it here rather than reiterating again the group in case no member is up. */
801 dea0921d Ermal
				if (!is_array($backupplan[$tier]))
802
					$backupplan[$tier] = array();
803 d8bf779b Ermal
				$backupplan[$tier][] = $gwname;
804 3d471a14 Ermal
805 fd8eeda5 Seth Mos
				/* check if the gateway is available before adding it to the array */
806 e0ba24f7 smos
				if (is_array($gateways_status[$gwname])) {
807 54b78cc1 Ermal
					$status = $gateways_status[$gwname];
808 3d471a14 Ermal
					$gwdown = false;
809 9af4b31b Ermal
					if (stristr($status['status'], "down")) {
810 50006cca PiBa-NL
						$msg = sprintf(gettext("MONITOR: %s is down, removing from routing group {$group['name']}"), $gwname);
811 3d471a14 Ermal
						$gwdown = true;
812
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
813
						/* packet loss */
814 50006cca PiBa-NL
						$msg = sprintf(gettext("MONITOR: %s has packet loss, removing from routing group {$group['name']}"), $gwname);
815 3d471a14 Ermal
						$gwdown = true;
816
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
817
						/* high latency */
818 50006cca PiBa-NL
						$msg = sprintf(gettext("MONITOR: %s has high latency, removing from routing group {$group['name']}"), $gwname);
819 3d471a14 Ermal
						$gwdown = true;
820
					}
821
					if ($gwdown == true) {
822 9f1d61d3 Scott Ullrich
						log_error($msg);
823
						notify_via_growl($msg);
824 10c3d4c0 Scott Ullrich
						notify_via_smtp($msg);
825 e0ba24f7 smos
					} else {
826 857ce5f3 Seth Mos
						/* Online add member */
827 dea0921d Ermal
						if (!is_array($tiers[$tier]))
828
							$tiers[$tier] = array();
829 857ce5f3 Seth Mos
						$tiers[$tier][] = $gwname;
830 e0ba24f7 smos
					}
831 33c06ef7 Ermal
				} else if (isset($gateways_arr[$gwname]['monitor_disable']))
832
					$tiers[$tier][] = $gwname;
833 fd8eeda5 Seth Mos
			}
834
			$tiers_count = count($tiers);
835 1500614c Ermal
			if ($tiers_count == 0) {
836 fd8eeda5 Seth Mos
				/* Oh dear, we have no members! Engage Plan B */
837 9132ae35 Ermal
				if (!$g['booting']) {
838 50006cca PiBa-NL
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
839 9132ae35 Ermal
					log_error($msg);
840
					notify_via_growl($msg);
841 72b4a1e8 jim-p
					//notify_via_smtp($msg);
842 9132ae35 Ermal
				}
843 3d471a14 Ermal
				$tiers = $backupplan;
844 fd8eeda5 Seth Mos
			}
845 09ae0c17 Seth Mos
			/* sort the tiers array by the tier key */
846
			ksort($tiers);
847 3d471a14 Ermal
848 fd8eeda5 Seth Mos
			/* we do not really foreach the tiers as we stop after the first tier */
849 1500614c Ermal
			foreach ($tiers as $tieridx => $tier) {
850 fd8eeda5 Seth Mos
				/* process all gateways in this tier */
851 1500614c Ermal
				foreach ($tier as $member) {
852 fd8eeda5 Seth Mos
					/* determine interface gateway */
853 5f53260a Ermal
					if (isset($gateways_arr[$member])) {
854
						$gateway = $gateways_arr[$member];
855
						$int = $gateway['interface'];
856
						$gatewayip = "";
857 f040882c Renato Botelho
						if(is_ipaddr($gateway['gateway']))
858 5f53260a Ermal
							$gatewayip = $gateway['gateway'];
859 1500614c Ermal
						else if (!empty($int))
860 5f53260a Ermal
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
861 f040882c Renato Botelho
862 f60003fa Phil Davis
						if (!empty($int)) {
863 44b054ce smos
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
864 f60003fa Phil Davis
							if (is_ipaddr($gatewayip)) {
865
								$groupmember = array();
866
								$groupmember['int']  = $int;
867
								$groupmember['gwip']  = $gatewayip;
868
								$groupmember['weight']  = isset($gateway['weight']) ? $gateway['weight'] : 1;
869
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member]))
870
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
871
								$gateway_groups_array[$group['name']][] = $groupmember;
872
							}
873 3d471a14 Ermal
						}
874 fd8eeda5 Seth Mos
					}
875
				}
876
				/* we should have the 1st available tier now, exit stage left */
877 1500614c Ermal
				if (count($gateway_groups_array[$group['name']]) > 0)
878 47c48e28 smos
					break;
879
				else
880 1500614c Ermal
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
881 fd8eeda5 Seth Mos
			}
882
		}
883
	}
884 1500614c Ermal
885 fe22a89b Ermal
	return ($gateway_groups_array);
886 fd8eeda5 Seth Mos
}
887
888 2468ae76 Scott Ullrich
/* Update DHCP WAN Interface ip address in gateway group item */
889
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
890
	global $config, $g;
891 f040882c Renato Botelho
	foreach($config['gateways']['gateway_item'] as & $gw) {
892 2468ae76 Scott Ullrich
		if($gw['interface'] == $interface) {
893
			$current_gw = get_interface_gateway($interface);
894
			if($gw['gateway'] <> $current_gw) {
895
				$gw['gateway'] = $current_gw;
896
				$changed = true;
897
			}
898
		}
899
	}
900
	if($changed && $current_gw)
901 addc0439 Renato Botelho
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
902 2468ae76 Scott Ullrich
}
903 fd8eeda5 Seth Mos
904 6dc3a5c2 Ermal Lu?i
function lookup_gateway_ip_by_name($name) {
905 fe22a89b Ermal
906 fbf0d4d3 smos
	$gateways_arr = return_gateways_array(false, true);
907 f040882c Renato Botelho
	foreach ($gateways_arr as $gname => $gw) {
908 d97eccf9 Renato Botelho
		if ($gw['name'] === $name || $gname === $name)
909 f040882c Renato Botelho
			return $gw['gateway'];
910
	}
911 66a96e72 Ermal
912
	return false;
913 6dc3a5c2 Ermal Lu?i
}
914
915
function lookup_gateway_monitor_ip_by_name($name) {
916 fe22a89b Ermal
917 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
918 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
919
		$gateway = $gateways_arr[$name];
920 68f291ff Ermal
		if(!is_ipaddr($gateway['monitor']))
921
			return $gateway['gateway'];
922 6dc3a5c2 Ermal Lu?i
923 9fd19334 gnhb
		return $gateway['monitor'];
924 f040882c Renato Botelho
	}
925 fe22a89b Ermal
926 f040882c Renato Botelho
	return (false);
927 6dc3a5c2 Ermal Lu?i
}
928
929
function lookup_gateway_interface_by_name($name) {
930
931 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
932 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
933 be2a18bf Phil Davis
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
934 fe22a89b Ermal
		return ($interfacegw);
935 f040882c Renato Botelho
	}
936 fe22a89b Ermal
937 f040882c Renato Botelho
	return (false);
938 6dc3a5c2 Ermal Lu?i
}
939
940 a2532739 Ermal Lu?i
function get_interface_gateway($interface, &$dynamic = false) {
941 5a5413bb Seth Mos
	global $config, $g;
942 6dc3a5c2 Ermal Lu?i
943 5a5413bb Seth Mos
	$gw = NULL;
944 6dc3a5c2 Ermal Lu?i
945 5a5413bb Seth Mos
	$gwcfg = $config['interfaces'][$interface];
946
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
947
		foreach($config['gateways']['gateway_item'] as $gateway) {
948
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
949
				$gw = $gateway['gateway'];
950 66a96e72 Ermal
				break;
951
			}
952 5a5413bb Seth Mos
		}
953 66a96e72 Ermal
	}
954 6dc3a5c2 Ermal Lu?i
955 5a5413bb Seth Mos
	// for dynamic interfaces we handle them through the $interface_router file.
956 2feb85af Seth Mos
	if (!is_ipaddrv4($gw) && !is_ipaddrv4($gwcfg['ipaddr'])) {
957 5a5413bb Seth Mos
		$realif = get_real_interface($interface);
958
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
959
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
960
			$dynamic = true;
961
		}
962
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
963
			$dynamic = "default";
964 f040882c Renato Botelho
965 5a5413bb Seth Mos
	}
966
967
	/* return gateway */
968
	return ($gw);
969
}
970
971
function get_interface_gateway_v6($interface, &$dynamic = false) {
972
	global $config, $g;
973 6dc3a5c2 Ermal Lu?i
974 5a5413bb Seth Mos
	$gw = NULL;
975
	$gwcfg = $config['interfaces'][$interface];
976 ed5c640d Seth Mos
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
977 5a5413bb Seth Mos
		foreach($config['gateways']['gateway_item'] as $gateway) {
978 640b3a9a Seth Mos
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
979 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
980
				break;
981
			}
982
		}
983
	}
984
985
	// for dynamic interfaces we handle them through the $interface_router file.
986 2feb85af Seth Mos
	if (!is_ipaddrv6($gw) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
987 5a5413bb Seth Mos
			$realif = get_real_interface($interface);
988
			if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
989
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
990
				$dynamic = true;
991
			}
992
			if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6"))
993
				$dynamic = "default";
994 f040882c Renato Botelho
995 5a5413bb Seth Mos
	}
996
	/* return gateway */
997
	return ($gw);
998 6dc3a5c2 Ermal Lu?i
}
999
1000 318189b6 smos
/* Check a IP address against a gateway IP or name
1001
 * to verify it's address family */
1002
function validate_address_family($ipaddr, $gwname) {
1003
	$v4ip = false;
1004
	$v6ip = false;
1005
	$v4gw = false;
1006
	$v6gw = false;
1007
1008
	if(is_ipaddrv4($ipaddr))
1009
		$v4ip = true;
1010
	if(is_ipaddrv6($ipaddr))
1011
		$v6ip = true;
1012
	if(is_ipaddrv4($gwname))
1013
		$v4gw = true;
1014
	if(is_ipaddrv6($gwname))
1015
		$v6gw = true;
1016
1017
	if($v4ip && $v4gw)
1018
		return true;
1019
	if($v6ip && $v6gw)
1020
		return true;
1021
1022
	/* still no match, carry on, lookup gateways */
1023
	if(is_ipaddrv4(lookup_gateway_ip_by_name($gwname)))
1024
		$v4gw = true;
1025
	if(is_ipaddrv6(lookup_gateway_ip_by_name($gwname)))
1026
		$v6gw = true;
1027 96cd928b smos
1028
	$gw_array = return_gateways_array();
1029
	if(is_array($gw_array[$gwname])) {
1030
		switch($gw_array[$gwname]['ipprotocol']) {
1031
			case "inet":
1032
				$v4gw = true;
1033
				break;
1034
			case "inet6":
1035
				$v6gw = true;
1036
				break;
1037
		}
1038 748ff86f Seth Mos
	}
1039 318189b6 smos
1040
	if($v4ip && $v4gw)
1041
		return true;
1042
	if($v6ip && $v6gw)
1043
		return true;
1044 f040882c Renato Botelho
1045 318189b6 smos
	return false;
1046
}
1047
1048 cdb0df65 smos
/* check if a interface is part of a gateway group */
1049
function interface_gateway_group_member($interface) {
1050
	global $config;
1051 c447a9fe Ermal
1052
	if (is_array($config['gateways']['gateway_group']))
1053 cdb0df65 smos
		$groups = $config['gateways']['gateway_group'];
1054
	else
1055
		return false;
1056
1057 f040882c Renato Botelho
	$gateways_arr = return_gateways_array(false, true);
1058 cdb0df65 smos
	foreach($groups as $group) {
1059
		if(is_array($group['item'])) {
1060
			foreach($group['item'] as $item) {
1061
				$elements = explode("|", $item);
1062
				$gwname = $elements[0];
1063 c447a9fe Ermal
				if ($interface == $gateways_arr[$gwname]['interface']) {
1064
					unset($gateways_arr);
1065 017817c2 smos
					return true;
1066 c447a9fe Ermal
				}
1067 cdb0df65 smos
			}
1068
		}
1069
	}
1070 c447a9fe Ermal
	unset($gateways_arr);
1071
1072 cdb0df65 smos
	return false;
1073
}
1074 318189b6 smos
1075 58b1112f Ermal
function gateway_is_gwgroup_member($name) {
1076
	global $config;
1077
1078
	if (is_array($config['gateways']['gateway_group']))
1079
		$groups = $config['gateways']['gateway_group'];
1080
	else
1081
		return false;
1082
1083
	$members = array();
1084
	foreach($groups as $group) {
1085
		if (is_array($group['item'])) {
1086
			foreach($group['item'] as $item) {
1087
				$elements = explode("|", $item);
1088
				$gwname = $elements[0];
1089
				if ($name == $elements[0])
1090
					$members[] = $group['name'];
1091
			}
1092
		}
1093
	}
1094
1095
	return $members;
1096
}
1097 c832f6bf smos
?>