Project

General

Profile

Download (37.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
  Copyright (C) 2008 Bill Marquette, Seth Mos
4
  Copyright (C) 2010 Ermal Luçi
5
  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
  1. Redistributions of source code must retain the above copyright notice,
11
  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
	pfSense_BUILDER_BINARIES:	/sbin/route	/usr/local/sbin/apinger
29
	pfSense_MODULE:	routing
30

    
31
 */
32
require_once("config.inc");
33
require_once("rrd.inc");
34

    
35
/* 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
		"down" => "10",
44
		"avg_delay_samples" => "10",
45
		"avg_loss_samples" => "50",
46
		"avg_loss_delay_samples" => "20");
47
}
48

    
49
/*
50
 * Creates monitoring configuration file and
51
 * adds appropriate static routes.
52
 */
53
function setup_gateways_monitor() {
54
	global $config, $g;
55

    
56
	$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
		@unlink("{$g['varrun_path']}/apinger.status");
61
		return;
62
	}
63

    
64
	$apinger_debug = "";
65
	if (isset($config['system']['apinger_debug']))
66
		$apinger_debug = "debug on";
67

    
68
	$apinger_default = return_apinger_defaults();
69
	$apingerconfig = <<<EOD
70

    
71
# pfSense apinger configuration file. Automatically Generated!
72

    
73
{$apinger_debug}
74

    
75
## User and group the pinger should run as
76
user "root"
77
group "wheel"
78

    
79
## Mailer to use (default: "/usr/lib/sendmail -t")
80
#mailer "/var/qmail/bin/qmail-inject"
81

    
82
## Location of the pid-file (default: "/var/run/apinger.pid")
83
pid_file "{$g['varrun_path']}/apinger.pid"
84

    
85
## Format of timestamp (%s macro) (default: "%b %d %H:%M:%S")
86
#timestamp_format "%Y%m%d%H%M%S"
87

    
88
status {
89
	## File where the status information should be written to
90
	file "{$g['varrun_path']}/apinger.status"
91
	## Interval between file updates
92
	## when 0 or not set, file is written only when SIGUSR1 is received
93
	interval 5s
94
}
95

    
96
########################################
97
# RRDTool status gathering configuration
98
# Interval between RRD updates
99
rrd interval 60s;
100

    
101
## These parameters can be overridden in a specific alarm configuration
102
alarm default {
103
	command on "/usr/local/sbin/pfSctl -c 'service reload dyndns %T' -c 'service reload ipsecdns' -c 'service reload openvpn %T' -c 'filter reload' "
104
	command off "/usr/local/sbin/pfSctl -c 'service reload dyndns %T' -c 'service reload ipsecdns' -c 'service reload openvpn %T' -c 'filter reload' "
105
	combine 10s
106
}
107

    
108
## "Down" alarm definition.
109
## This alarm will be fired when target doesn't respond for 30 seconds.
110
alarm down "down" {
111
	time {$apinger_default['down']}s
112
}
113

    
114
## "Delay" alarm definition.
115
## This alarm will be fired when responses are delayed more than 200ms
116
## it will be canceled, when the delay drops below 100ms
117
alarm delay "delay" {
118
	delay_low {$apinger_default['latencylow']}ms
119
	delay_high {$apinger_default['latencyhigh']}ms
120
}
121

    
122
## "Loss" alarm definition.
123
## This alarm will be fired when packet loss goes over 20%
124
## it will be canceled, when the loss drops below 10%
125
alarm loss "loss" {
126
	percent_low {$apinger_default['losslow']}
127
	percent_high {$apinger_default['losshigh']}
128
}
129

    
130
target default {
131
	## How often the probe should be sent
132
	interval {$apinger_default['interval']}s
133

    
134
	## How many replies should be used to compute average delay
135
	## for controlling "delay" alarms
136
	avg_delay_samples {$apinger_default['avg_delay_samples']}
137

    
138
	## How many probes should be used to compute average loss
139
	avg_loss_samples {$apinger_default['avg_loss_samples']}
140

    
141
	## The delay (in samples) after which loss is computed
142
	## without this delays larger than interval would be treated as loss
143
	avg_loss_delay_samples {$apinger_default['avg_loss_delay_samples']}
144

    
145
	## Names of the alarms that may be generated for the target
146
	alarms "down","delay","loss"
147

    
148
	## Location of the RRD
149
	#rrd file "{$g['vardb_path']}/rrd/apinger-%t.rrd"
150
}
151

    
152
EOD;
153

    
154
	$monitor_ips = array();
155
	foreach($gateways_arr as $name => $gateway) {
156
		/* Do not monitor if such was requested */
157
		if (isset($gateway['monitor_disable']))
158
			continue;
159
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
160
			if (is_ipaddr($gateway['gateway']))
161
				$gateway['monitor'] = $gateway['gateway'];
162
			else /* No chance to get an ip to monitor skip target. */
163
				continue;
164
		}
165

    
166
		/* if the monitor address is already used before, skip */
167
		if(in_array($gateway['monitor'], $monitor_ips))
168
			continue;
169

    
170
		/* Interface ip is needed since apinger will bind a socket to it. 
171
		 * However the config GUI should already have checked this and when 
172
		 * PPoE is used the IP address is set to "dynamic". So using is_ipaddrv4
173
		 * or is_ipaddrv6 to identify packet type would be wrong, especially as
174
		 * further checks (that can cope with the "dynamic" case) are present inside
175
		 * the if block. So using $gateway['ipprotocol'] is the better option.
176
		 */
177
		if ($gateway['ipprotocol'] == "inet") { // This is an IPv4 gateway...
178
			$gwifip = find_interface_ip($gateway['interface'], true);
179
			if (!is_ipaddrv4($gwifip))
180
				continue; //Skip this target
181

    
182
			/*
183
			 * If the gateway is the same as the monitor we do not add a
184
			 * route as this will break the routing table.
185
			 * Add static routes for each gateway with their monitor IP
186
			 * not strictly necessary but is a added level of protection.
187
			 */
188
			if (is_ipaddrv4($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
189
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
190
				if (interface_isppp_type($gateway['friendlyiface']))
191
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
192
						" -iface " . escapeshellarg($gateway['interface']), true);
193
				else
194
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
195
						" " . escapeshellarg($gateway['gateway']), true);
196

    
197
				pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp");
198
			}
199
		} else if ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway...
200
			if ($gateway['monitor'] == $gateway['gateway']) {
201
				/* link locals really need a different src ip */
202
				if (is_linklocal($gateway['gateway'])) {
203
					if (!strpos($gateway['gateway'], '%'))
204
						$gateway['gateway'] .= '%' . $gateway['interface'];
205
					$gwifip = find_interface_ipv6_ll($gateway['interface'], true);
206
				} else {
207
					$gwifip = find_interface_ipv6($gateway['interface'], true);
208
				}
209
			} else {
210
				/* 'monitor' has been set, so makes sure it has precedence over
211
				 * 'gateway' in defining the source IP. Otherwise if 'gateway'
212
				 * is a local link and 'monitor' is global routable then the
213
				 * ICMP6 response would not find its way back home...
214
				 */
215
				$gwifip = find_interface_ipv6($gateway['interface'], true);
216
			}
217

    
218
			/* Make sure srcip and target have scope defined when they are ll */
219
			if (is_linklocal($gwifip) && !strpos($gwifip, '%'))
220
				$gwifip .= '%' . $gateway['interface'];
221
			if (is_linklocal($gateway['monitor']) && !strpos($gateway['monitor'], '%'))
222
				$gateway['monitor'] .= "%{$gateway['interface']}";
223

    
224
			if (!is_ipaddrv6($gwifip))
225
				continue; //Skip this target
226

    
227
			/*
228
			 * If the gateway is the same as the monitor we do not add a
229
			 * route as this will break the routing table.
230
			 * Add static routes for each gateway with their monitor IP
231
			 * not strictly necessary but is a added level of protection.
232
			 */
233
			if ($gateway['gateway'] != $gateway['monitor']) {
234
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
235
				if (interface_isppp_type($gateway['friendlyiface']))
236
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
237
						" -iface " . escapeshellarg($gateway['interface']), true);
238
				else
239
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
240
						" " . escapeshellarg($gateway['gateway']), true);
241

    
242
				pfSense_kill_states("::0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmpv6");
243
			}
244
		} else
245
			continue;
246

    
247
		$monitor_ips[] = $gateway['monitor'];
248
		$apingercfg = "target \"{$gateway['monitor']}\" {\n";
249
		$apingercfg .= "	description \"{$name}\"\n";
250
		$apingercfg .= "	srcip \"{$gwifip}\"\n";
251

    
252
		## How often the probe should be sent
253
		if (!empty($gateway['interval']) &&  is_numeric($gateway['interval'])) {
254
			$interval = intval($gateway['interval']);	# Restrict to Integer
255
			if ($interval <  1) $interval =  1;	# Minimum
256
			if ($interval != $apinger_default['interval'])	# If not default value
257
				$apingercfg .= "	interval " . $interval . "s\n";
258
		}
259

    
260
		## How many replies should be used to compute average delay 
261
		## for controlling "delay" alarms
262
		if (!empty($gateway['avg_delay_samples']) && is_numeric($gateway['avg_delay_samples'])) {
263
			$avg_delay_samples = intval($gateway['avg_delay_samples']);	# Restrict to Integer
264
			if ($avg_delay_samples <  1) $avg_delay_samples =  1;	# Minimum
265
			if ($avg_delay_samples != $apinger_default['avg_delay_samples'])	# If not default value
266
				$apingercfg .= "	avg_delay_samples " . $avg_delay_samples . "\n";
267
		}
268

    
269
		## How many probes should be used to compute average loss
270
		if (!empty($gateway['avg_loss_samples']) && is_numeric($gateway['avg_loss_samples'])) {
271
			$avg_loss_samples = intval($gateway['avg_loss_samples']);	# Restrict to Integer
272
			if ($avg_loss_samples < 1) $avg_loss_samples = 1;	# Minimum
273
			if ($avg_loss_samples != $apinger_default['avg_loss_samples'])	# If not default value
274
				$apingercfg .= "	avg_loss_samples " . $avg_loss_samples . "\n";
275
		}
276

    
277
		## The delay (in samples) after which loss is computed
278
		## without this delays larger than interval would be treated as loss
279
		if (!empty($gateway['avg_loss_delay_samples']) && is_numeric($gateway['avg_loss_delay_samples'])) {
280
			$avg_loss_delay_samples = intval($gateway['avg_loss_delay_samples']);	# Restrict to Integer
281
			if ($avg_loss_delay_samples < 1) $avg_loss_delay_samples = 1;	# Minimum
282
			if ($avg_loss_delay_samples != $apinger_default['avg_loss_delay_samples'])	# If not default value
283
				$apingercfg .= "	avg_loss_delay_samples " . $avg_loss_delay_samples . "\n";
284
		}
285

    
286
		$alarms = "";
287
		$alarmscfg = "";
288
		$override = false;
289
		if (!empty($gateway['losslow'])) {
290
			$alarmscfg .= "alarm loss \"{$name}loss\" {\n";
291
			$alarmscfg .= "\tpercent_low {$gateway['losslow']}\n";
292
			$alarmscfg .= "\tpercent_high {$gateway['losshigh']}\n";
293
			$alarmscfg .= "}\n";
294
			$alarms .= "\"{$name}loss\"";
295
			$override = true;
296
		} else {
297
			if ($override == true)
298
				$alarms .= ",";
299
			$alarms .= "\"loss\"";
300
			$override = true;
301
		}
302
		if (!empty($gateway['latencylow'])) {
303
			$alarmscfg .= "alarm delay \"{$name}delay\" {\n";
304
			$alarmscfg .= "\tdelay_low {$gateway['latencylow']}ms\n";
305
			$alarmscfg .= "\tdelay_high {$gateway['latencyhigh']}ms\n";
306
			$alarmscfg .= "}\n";
307
			if ($override == true)
308
				$alarms .= ",";
309
			$alarms .= "\"{$name}delay\"";
310
			$override = true;
311
		} else {
312
			if ($override == true)
313
				$alarms .= ",";
314
			$alarms .= "\"delay\"";
315
			$override = true;
316
		}
317
		if (!empty($gateway['down'])) {
318
			$alarmscfg .= "alarm down \"{$name}down\" {\n";
319
			$alarmscfg .= "\ttime {$gateway['down']}s\n";
320
			$alarmscfg .= "}\n";
321
			if ($override == true)
322
				$alarms .= ",";
323
			$alarms .= "\"{$name}down\"";
324
			$override = true;
325
		} else {
326
			if ($override == true)
327
				$alarms .= ",";
328
			$alarms .= "\"down\"";
329
			$override = true;
330
		}
331
		if ($override == true)
332
			$apingercfg .= "\talarms override {$alarms};\n";
333

    
334
		if (isset($gateway['force_down']))
335
			$apingercfg .= "\tforce_down on\n";
336

    
337
		$apingercfg .= "	rrd file \"{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd\"\n";
338
		$apingercfg .= "}\n";
339
		$apingercfg .= "\n";
340

    
341
		$apingerconfig .= $alarmscfg;
342
		$apingerconfig .= $apingercfg;
343

    
344
		# Create gateway quality RRD with settings more suitable for pfSense graph set, 
345
		# since apinger uses default step (300; 5 minutes) and other settings that don't 
346
		# match the pfSense gateway quality graph set.
347
		create_gateway_quality_rrd("{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd");
348
	}
349
	@file_put_contents("{$g['varetc_path']}/apinger.conf", $apingerconfig);
350
	unset($apingerconfig);
351

    
352
 	/* Restart apinger process */
353
	if (isvalidpid("{$g['varrun_path']}/apinger.pid"))
354
		sigkillbypid("{$g['varrun_path']}/apinger.pid", "HUP");
355
	else {
356
		/* start a new apinger process */
357
		@unlink("{$g['varrun_path']}/apinger.status");
358
		sleep(1);
359
		mwexec_bg("/usr/local/sbin/apinger -c {$g['varetc_path']}/apinger.conf");
360
		sleep(1);
361
		sigkillbypid("{$g['varrun_path']}/apinger.pid", "USR1");
362
	}
363

    
364
	return 0;
365
}
366

    
367
/* return the status of the apinger targets as a array */
368
function return_gateways_status($byname = false) {
369
	global $config, $g;
370

    
371
	$apingerstatus = array();
372
	/* Always get the latest status from apinger */
373
	if (file_exists("{$g['varrun_path']}/apinger.pid"))
374
                sigkillbypid("{$g['varrun_path']}/apinger.pid", "USR1");
375
	if (file_exists("{$g['varrun_path']}/apinger.status")) {
376
		$apingerstatus = file("{$g['varrun_path']}/apinger.status");
377
	} else
378
		$apingerstatus = array();
379

    
380
	$status = array();
381
	foreach($apingerstatus as $line) {
382
		$info = explode("|", $line);
383
		if ($byname == false)
384
			$target = $info[0];
385
		else
386
			$target = $info[2];
387

    
388
		$status[$target] = array();
389
		$status[$target]['monitorip'] = $info[0];
390
		$status[$target]['srcip'] = $info[1];
391
		$status[$target]['name'] = $info[2];
392
		$status[$target]['lastcheck'] = $info[5] ? date('r', $info[5]) : date('r');
393
		$status[$target]['delay'] = empty($info[6]) ? "0ms" : round($info[6], 1) ."ms" ;
394
		$status[$target]['loss'] = empty($info[7]) ? "0.0%" : round($info[7], 1) . "%";
395
		$status[$target]['status'] = trim($info[8]);
396
	}
397

    
398
	/* tack on any gateways that have monitoring disabled
399
	 * or are down, which could cause gateway groups to fail */
400
	$gateways_arr = return_gateways_array();
401
	foreach($gateways_arr as $gwitem) {
402
		if(!isset($gwitem['monitor_disable']))
403
			continue;
404
		if(!is_ipaddr($gwitem['monitorip'])) {
405
			$realif = $gwitem['interface'];
406
			$tgtip = get_interface_gateway($realif);
407
			if (!is_ipaddr($tgtip))
408
				$tgtip = "none";
409
			$srcip = find_interface_ip($realif);
410
		} else {
411
			$tgtip = $gwitem['monitorip'];
412
			$srcip = find_interface_ip($realif);
413
		}
414
		if($byname == true)
415
			$target = $gwitem['name'];
416
		else
417
			$target = $tgtip;
418

    
419
		/* failsafe for down interfaces */
420
		if($target == "none") {
421
			$target = $gwitem['name'];
422
			$status[$target]['name'] = $gwitem['name'];
423
			$status[$target]['lastcheck'] = date('r');
424
			$status[$target]['delay'] = "0.0ms";
425
			$status[$target]['loss'] = "100.0%";
426
			$status[$target]['status'] = "down";
427
		} else {
428
			$status[$target]['monitorip'] = $tgtip;
429
			$status[$target]['srcip'] = $srcip;
430
			$status[$target]['name'] = $gwitem['name'];
431
			$status[$target]['lastcheck'] = date('r');
432
			$status[$target]['delay'] = "0.0ms";
433
			$status[$target]['loss'] = "0.0%";
434
			$status[$target]['status'] = "none";
435
		}
436
	}
437
	return($status);
438
}
439

    
440
/* Return all configured gateways on the system */
441
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
442
	global $config, $g;
443

    
444
	$gateways_arr = array();
445

    
446
	$found_defaultv4 = 0;
447
	$found_defaultv6 = 0;
448

    
449
	// Ensure the interface cache is up to date first
450
	$interfaces = get_interface_arr(true);
451
	$interfaces_v4 = array();
452
	$interfaces_v6 = array();
453

    
454
	$i = -1;
455
	/* Process/add all the configured gateways. */
456
	if (is_array($config['gateways']['gateway_item'])) {
457
		foreach ($config['gateways']['gateway_item'] as $gateway) {
458
			/* Increment it here to do not skip items */
459
			$i++;
460

    
461
			if (empty($config['interfaces'][$gateway['interface']])) {
462
				if ($inactive === false)
463
					continue;
464
				else
465
					$gateway['inactive'] = true;
466
			}
467
			$wancfg = $config['interfaces'][$gateway['interface']];
468

    
469
			/* skip disabled interfaces */
470
			if ($disabled === false && (!isset($wancfg['enable']) || isset($gateway['disabled'])))
471
				continue;
472

    
473
			/* if the gateway is dynamic and we can find the IPv4, Great! */
474
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
475
				if ($gateway['ipprotocol'] == "inet") {
476
					/* we know which interfaces is dynamic, this should be made a function */
477
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
478
					/* no IP address found, set to dynamic */
479
					if (!is_ipaddrv4($gateway['gateway']))
480
						$gateway['gateway'] = "dynamic";
481
					$gateway['dynamic'] = true;
482
				}
483

    
484
				/* if the gateway is dynamic and we can find the IPv6, Great! */
485
				else if ($gateway['ipprotocol'] == "inet6") {
486
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
487
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
488
					/* no IPv6 address found, set to dynamic */
489
					if (!is_ipaddrv6($gateway['gateway']))
490
						$gateway['gateway'] = "dynamic";
491
					$gateway['dynamic'] = true;
492
				}
493
			} else {
494
				/* getting this detection right is hard at this point because we still don't
495
				 * store the address family in the gateway item */
496
				if (is_ipaddrv4($gateway['gateway']))
497
					$gateway['ipprotocol'] = "inet";
498
				else if(is_ipaddrv6($gateway['gateway']))
499
					$gateway['ipprotocol'] = "inet6";
500
			}
501

    
502
			if (isset($gateway['monitor_disable']))
503
				$gateway['monitor_disable'] = true;
504
			else if (empty($gateway['monitor']))
505
				$gateway['monitor'] = $gateway['gateway'];
506

    
507
			$gateway['friendlyiface'] = $gateway['interface'];
508

    
509
			/* special treatment for tunnel interfaces */
510
			if ($gateway['ipprotocol'] == "inet6") {
511
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
512
				$interfaces_v6[$gateway['friendlyiface']] = $gateway['friendlyiface'];
513
			} else {
514
				$gateway['interface'] = get_real_interface($gateway['interface'], "all", false, false);
515
				$interfaces_v4[$gateway['friendlyiface']] = $gateway['friendlyiface'];
516
			}
517

    
518
			/* entry has a default flag, use it */
519
			if (isset($gateway['defaultgw'])) {
520
				if ($gateway['ipprotocol'] == "inet") {
521
					$gateway['defaultgw'] = true;
522
					$found_defaultv4 = 1;
523
				} else if ($gateway['ipprotocol'] == "inet6") {
524
					$gateway['defaultgw'] = true;
525
					$found_defaultv6 = 1;
526
				}
527
			}
528
			/* include the gateway index as the attribute */
529
			$gateway['attribute'] = $i;
530

    
531
			$gateways_arr[$gateway['name']] = $gateway;
532
		}
533
	}
534
	unset($gateway);
535

    
536
	/* Loop through all interfaces with a gateway and add it to a array */
537
	if ($disabled == false)
538
		$iflist = get_configured_interface_with_descr();
539
	else
540
		$iflist = get_configured_interface_with_descr(false, true);
541

    
542
	/* Process/add dynamic v4 gateways. */
543
	foreach($iflist as $ifname => $friendly ) {
544
		if(! interface_has_gateway($ifname))
545
			continue;
546

    
547
		if (empty($config['interfaces'][$ifname]))
548
			continue;
549

    
550
		$ifcfg = &$config['interfaces'][$ifname];
551
		if(!isset($ifcfg['enable']))
552
			continue;
553

    
554
		if(!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr']))
555
			continue;
556

    
557
		if (isset($interfaces_v4[$ifname]))
558
			continue;
559

    
560
		$ctype = "";
561
		switch($ifcfg['ipaddr']) {
562
			case "dhcp":
563
			case "pppoe":
564
			case "pptp":
565
			case "ppp":
566
				$ctype = strtoupper($ifcfg['ipaddr']);
567
				break;
568
			default:
569
				$tunnelif = substr($ifcfg['if'], 0, 3);
570
				if (substr($ifcfg['if'], 0, 4) ==  "ovpn") {
571
					// if current iface is an ovpn server endpoint then check its type, skip tap only
572
					if (substr($ifcfg['if'], 4, 1) == 's') {
573
						$ovpnid = substr($ifcfg['if'], 5);
574
						if (is_array($config['openvpn']['openvpn-server'])) {
575
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
576
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
577
									if ($ovpnserverconf['dev_mode'] == "tap")
578
										continue 3;
579
								}
580
							}
581
						}
582
					}
583
					$ctype = "VPNv4";
584
				} else if ($tunnelif == "gif" || $tunnelif == "gre")
585
					$ctype = "TUNNELv4";
586
				break;
587
		}
588
		$ctype = "_". strtoupper($ctype);
589

    
590
		$gateway = array();
591
		$gateway['dynamic'] = false;
592
		$gateway['ipprotocol'] = "inet";
593
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
594
		$gateway['interface'] = get_real_interface($ifname);
595
		$gateway['friendlyiface'] = $ifname;
596
		$gateway['name'] = "{$friendly}{$ctype}";
597
		$gateway['attribute'] = "system";
598

    
599
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
600
			$gateway['defaultgw'] = true;
601
			$gateway['dynamic'] = true;
602
			$found_defaultv4 = 1;
603
		}
604
		/* Loopback dummy for dynamic interfaces without a IP */
605
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true)
606
			$gateway['gateway'] = "dynamic";
607

    
608
		/* automatically skip known static and dynamic gateways we have a array entry for */
609
		foreach($gateways_arr as $gateway_item) {
610
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
611
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
612
					continue 2;
613
		}
614

    
615
		if (is_ipaddrv4($gateway['gateway']))
616
			$gateway['monitor'] = $gateway['gateway'];
617

    
618
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
619
		$gateways_arr[$gateway['name']] = $gateway;
620
	}
621
	unset($gateway);
622

    
623
	/* Process/add dynamic v6 gateways. */
624
	foreach($iflist as $ifname => $friendly ) {
625
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
626
		if (!isset($config['system']['ipv6allow']))
627
			break;
628

    
629
		if(! interface_has_gatewayv6($ifname))
630
			continue;
631

    
632
		if (empty($config['interfaces'][$ifname]))
633
			continue;
634

    
635
		$ifcfg = &$config['interfaces'][$ifname];
636
		if(!isset($ifcfg['enable']))
637
			continue;
638

    
639
		if(!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
640
			continue;
641

    
642
		if(isset($interfaces_v6[$ifname]))
643
			continue;
644

    
645
		$ctype = "";
646
		switch($ifcfg['ipaddrv6']) {
647
			case "slaac":
648
			case "dhcp6":
649
			case "6to4":
650
			case "6rd":
651
				$ctype = strtoupper($ifcfg['ipaddrv6']);
652
				break;
653
			default:
654
				$tunnelif = substr($ifcfg['if'], 0, 3);
655
				if (substr($ifcfg['if'], 0, 4) ==  "ovpn") {
656
					// if current iface is an ovpn server endpoint then check its type, skip tap only
657
					if (substr($ifcfg['if'], 4, 1) == 's') {
658
						$ovpnid = substr($ifcfg['if'], 5);
659
						if (is_array($config['openvpn']['openvpn-server'])) {
660
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
661
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
662
									if ($ovpnserverconf['dev_mode'] == "tap")
663
										continue 3;
664
								}
665
							}
666
						}
667
					}
668
					$ctype = "VPNv6";
669
				} else if ($tunnelif == "gif" || $tunnelif == "gre")
670
					$ctype = "TUNNELv6";
671
				break;
672
		}
673
		$ctype = "_". strtoupper($ctype);
674

    
675
		$gateway = array();
676
		$gateway['dynamic'] = false;
677
		$gateway['ipprotocol'] = "inet6";
678
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
679
		$gateway['interface'] = get_real_interface($ifname, "inet6");
680
		switch($ifcfg['ipaddrv6']) {
681
			case "6rd":
682
			case "6to4":
683
				$gateway['dynamic'] = "default";
684
				break;
685
		}
686
		$gateway['friendlyiface'] = $ifname;
687
		$gateway['name'] = "{$friendly}{$ctype}";
688
		$gateway['attribute'] = "system";
689

    
690
		if (($gateway['dynamic'] === "default")  && ($found_defaultv6 == 0)) {
691
			$gateway['defaultgw'] = true;
692
			$gateway['dynamic'] = true;
693
			$found_defaultv6 = 1;
694
		}
695

    
696
		/* Loopback dummy for dynamic interfaces without a IP */
697
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true)
698
			$gateway['gateway'] = "dynamic";
699

    
700
		/* automatically skip known static and dynamic gateways we have a array entry for */
701
		foreach($gateways_arr as $gateway_item) {
702
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
703
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
704
					continue 2;
705
		}
706

    
707
		if (is_ipaddrv6($gateway['gateway']))
708
			$gateway['monitor'] = $gateway['gateway'];
709

    
710
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
711
		$gateways_arr[$gateway['name']] = $gateway;
712
	}
713
	unset($gateway);
714

    
715
	/* FIXME: Should this be enabled.
716
	 * Some interface like wan might be default but have no info recorded
717
	 * the config. */
718
	/* this is a fallback if all else fails and we want to get packets out @smos */
719
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
720
		foreach ($gateways_arr as &$gateway) {
721
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
722
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
723
					$gateway['defaultgw'] = true;
724
					$found_defaultv4 = 1;
725
				}
726
			}
727
			else if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
728
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
729
					$gateway['defaultgw'] = true;
730
					$found_defaultv6 = 1;
731
				}
732
			}
733
		}
734
	}
735

    
736
	if($localhost === true) {
737
		/* attach localhost for Null routes */
738
		$gwlo4 = array();
739
		$gwlo4['name'] = "Null4";
740
		$gwlo4['interface'] = "lo0";
741
		$gwlo4['ipprotocol'] = "inet";
742
		$gwlo4['gateway'] = "127.0.0.1";
743
		$gwlo6 = array();
744
		$gwlo6['name'] = "Null6";
745
		$gwlo6['interface'] = "lo0";
746
		$gwlo6['ipprotocol'] = "inet6";
747
		$gwlo6['gateway'] = "::1";
748
		$gateways_arr['Null4'] = $gwlo4;
749
		$gateways_arr['Null6'] = $gwlo6;
750
	}
751
	return($gateways_arr);
752
}
753

    
754
function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) {
755
	global $config, $g;
756
	/*
757
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
758
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
759
	 */
760
	$upgw = '';
761
	$dfltgwname = '';
762
	$dfltgwdown = false;
763
	$dfltgwfound = false;
764
	foreach ($gateways_arr as $gwname => $gwsttng) {
765
		if (($gwsttng['ipprotocol'] == $ipprotocol) && isset($gwsttng['defaultgw'])) {
766
			$dfltgwfound = true;
767
			$dfltgwname = $gwname;
768
			if (!isset($gwsttng['monitor_disable']) && stristr($gateways_status[$gwname]['status'], "down"))
769
				$dfltgwdown = true;
770
		}
771
		/* Keep a record of the last up gateway */
772
		/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
773
		if (empty($upgw) && ($gwsttng['ipprotocol'] == $ipprotocol) && (isset($gwsttng['monitor_disable']) || !stristr($gateways_status[$gwname]['status'], "down")) && $gwsttng[$gwname]['friendlyiface'] != "lan")
774
			$upgw = $gwname;
775
		if ($dfltgwdown == true && !empty($upgw))
776
			break;
777
	}
778
	if ($dfltgwfound == false) {
779
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
780
		if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down"))
781
			$dfltgwdown = true;
782
	}
783
	if ($dfltgwdown == true && !empty($upgw)) {
784
		if ($gateways_arr[$upgw]['gateway'] == "dynamic")
785
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
786
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
787
			log_error("Default gateway down setting {$upgw} as default!");
788
			if(is_ipaddrv6($gateways_arr[$upgw]['gateway'])) {
789
				$inetfamily = "-inet6";
790
			} else {
791
				$inetfamily = "-inet";
792
			}
793
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
794
		}
795
	} else if (!empty($dfltgwname)) {
796
		$defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n");
797
		if ($ipprotocol == 'inet6' && !is_ipaddrv6($gateways_arr[$dfltgwname]['gateway']))
798
			return;
799
		if ($ipprotocol == 'inet' && !is_ipaddrv4($gateways_arr[$dfltgwname]['gateway']))
800
			return;
801
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway'])
802
			mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}");
803
	}
804
}
805

    
806
/*
807
 * Return an array with all gateway groups with name as key
808
 * All gateway groups will be processed before returning the array.
809
 */
810
function return_gateway_groups_array() {
811
	global $config, $g;
812

    
813
	/* fetch the current gateways status */
814
	$gateways_status = return_gateways_status(true);
815
	$gateways_arr = return_gateways_array();
816
	$gateway_groups_array = array();
817

    
818
	if (isset($config['system']['gw_switch_default'])) {
819
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
820
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
821
	}
822
	if (is_array($config['gateways']['gateway_group'])) {
823
		$carplist = get_configured_carp_interface_list();
824
		foreach ($config['gateways']['gateway_group'] as $group) {
825
			/* create array with group gateways members separated by tier */
826
			$tiers = array();
827
			$backupplan = array();
828
			$gwvip_arr = array();
829
			foreach ($group['item'] as $item) {
830
				list($gwname, $tier, $vipname) = explode("|", $item);
831

    
832
				if (is_ipaddr($carplist[$vipname])) {
833
					if (!is_array($gwvip_arr[$group['name']]))
834
						$gwvip_arr[$group['name']] = array();
835
					$gwvip_arr[$group['name']][$gwname] = $vipname;
836
				}
837

    
838
				/* Do it here rather than reiterating again the group in case no member is up. */
839
				if (!is_array($backupplan[$tier]))
840
					$backupplan[$tier] = array();
841
				$backupplan[$tier][] = $gwname;
842

    
843
				/* check if the gateway is available before adding it to the array */
844
				if (is_array($gateways_status[$gwname])) {
845
					$status = $gateways_status[$gwname];
846
					$gwdown = false;
847
					if (stristr($status['status'], "down")) {
848
						$msg = sprintf(gettext("MONITOR: %s is down, omitting from routing group {$group['name']}"), $gwname);
849
						$gwdown = true;
850
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
851
						/* packet loss */
852
						$msg = sprintf(gettext("MONITOR: %s has packet loss, omitting from routing group {$group['name']}"), $gwname);
853
						$gwdown = true;
854
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
855
						/* high latency */
856
						$msg = sprintf(gettext("MONITOR: %s has high latency, omitting from routing group {$group['name']}"), $gwname);
857
						$gwdown = true;
858
					}
859
					if ($gwdown == true) {
860
						log_error($msg);
861
						notify_via_growl($msg);
862
						notify_via_smtp($msg);
863
					} else {
864
						/* Online add member */
865
						if (!is_array($tiers[$tier]))
866
							$tiers[$tier] = array();
867
						$tiers[$tier][] = $gwname;
868
					}
869
				} else if (isset($gateways_arr[$gwname]['monitor_disable']))
870
					$tiers[$tier][] = $gwname;
871
			}
872
			$tiers_count = count($tiers);
873
			if ($tiers_count == 0) {
874
				/* Oh dear, we have no members! Engage Plan B */
875
				if (!platform_booting()) {
876
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
877
					log_error($msg);
878
					notify_via_growl($msg);
879
					//notify_via_smtp($msg);
880
				}
881
				$tiers = $backupplan;
882
			}
883
			/* sort the tiers array by the tier key */
884
			ksort($tiers);
885

    
886
			/* we do not really foreach the tiers as we stop after the first tier */
887
			foreach ($tiers as $tieridx => $tier) {
888
				/* process all gateways in this tier */
889
				foreach ($tier as $member) {
890
					/* determine interface gateway */
891
					if (isset($gateways_arr[$member])) {
892
						$gateway = $gateways_arr[$member];
893
						$int = $gateway['interface'];
894
						$gatewayip = "";
895
						if(is_ipaddr($gateway['gateway']))
896
							$gatewayip = $gateway['gateway'];
897
						else if (!empty($int))
898
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
899

    
900
						if (!empty($int)) {
901
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
902
							if (is_ipaddr($gatewayip)) {
903
								$groupmember = array();
904
								$groupmember['int']  = $int;
905
								$groupmember['gwip']  = $gatewayip;
906
								$groupmember['weight']  = isset($gateway['weight']) ? $gateway['weight'] : 1;
907
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member]))
908
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
909
								$gateway_groups_array[$group['name']][] = $groupmember;
910
							}
911
						}
912
					}
913
				}
914
				/* we should have the 1st available tier now, exit stage left */
915
				if (count($gateway_groups_array[$group['name']]) > 0)
916
					break;
917
				else
918
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
919
			}
920
		}
921
	}
922

    
923
	return ($gateway_groups_array);
924
}
925

    
926
/* Update DHCP WAN Interface ip address in gateway group item */
927
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
928
	global $config, $g;
929
	foreach($config['gateways']['gateway_item'] as & $gw) {
930
		if($gw['interface'] == $interface) {
931
			$current_gw = get_interface_gateway($interface);
932
			if($gw['gateway'] <> $current_gw) {
933
				$gw['gateway'] = $current_gw;
934
				$changed = true;
935
			}
936
		}
937
	}
938
	if($changed && $current_gw)
939
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
940
}
941

    
942
function lookup_gateway_ip_by_name($name) {
943

    
944
	$gateways_arr = return_gateways_array(false, true);
945
	foreach ($gateways_arr as $gname => $gw) {
946
		if ($gw['name'] === $name || $gname === $name)
947
			return $gw['gateway'];
948
	}
949

    
950
	return false;
951
}
952

    
953
function lookup_gateway_monitor_ip_by_name($name) {
954

    
955
	$gateways_arr = return_gateways_array(false, true);
956
	if (!empty($gateways_arr[$name])) {
957
		$gateway = $gateways_arr[$name];
958
		if(!is_ipaddr($gateway['monitor']))
959
			return $gateway['gateway'];
960

    
961
		return $gateway['monitor'];
962
	}
963

    
964
	return (false);
965
}
966

    
967
function lookup_gateway_interface_by_name($name) {
968

    
969
	$gateways_arr = return_gateways_array(false, true);
970
	if (!empty($gateways_arr[$name])) {
971
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
972
		return ($interfacegw);
973
	}
974

    
975
	return (false);
976
}
977

    
978
function get_interface_gateway($interface, &$dynamic = false) {
979
	global $config, $g;
980

    
981
	$gw = NULL;
982

    
983
	$gwcfg = $config['interfaces'][$interface];
984
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
985
		foreach($config['gateways']['gateway_item'] as $gateway) {
986
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
987
				$gw = $gateway['gateway'];
988
				break;
989
			}
990
		}
991
	}
992

    
993
	// for dynamic interfaces we handle them through the $interface_router file.
994
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
995
		$realif = get_real_interface($interface);
996
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
997
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
998
			$dynamic = true;
999
		}
1000
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
1001
			$dynamic = "default";
1002

    
1003
	}
1004

    
1005
	/* return gateway */
1006
	return ($gw);
1007
}
1008

    
1009
function get_interface_gateway_v6($interface, &$dynamic = false) {
1010
	global $config, $g;
1011

    
1012
	$gw = NULL;
1013
	$gwcfg = $config['interfaces'][$interface];
1014
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1015
		foreach($config['gateways']['gateway_item'] as $gateway) {
1016
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1017
				$gw = $gateway['gateway'];
1018
				break;
1019
			}
1020
		}
1021
	}
1022

    
1023
	// for dynamic interfaces we handle them through the $interface_router file.
1024
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1025
			$realif = get_real_interface($interface);
1026
			if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1027
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1028
				$dynamic = true;
1029
			}
1030
			if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6"))
1031
				$dynamic = "default";
1032

    
1033
	}
1034
	/* return gateway */
1035
	return ($gw);
1036
}
1037

    
1038
/* Check a IP address against a gateway IP or name
1039
 * to verify it's address family */
1040
function validate_address_family($ipaddr, $gwname) {
1041
	$v4ip = false;
1042
	$v6ip = false;
1043
	$v4gw = false;
1044
	$v6gw = false;
1045

    
1046
	if(is_ipaddrv4($ipaddr))
1047
		$v4ip = true;
1048
	if(is_ipaddrv6($ipaddr))
1049
		$v6ip = true;
1050
	if(is_ipaddrv4($gwname))
1051
		$v4gw = true;
1052
	if(is_ipaddrv6($gwname))
1053
		$v6gw = true;
1054

    
1055
	if($v4ip && $v4gw)
1056
		return true;
1057
	if($v6ip && $v6gw)
1058
		return true;
1059

    
1060
	/* still no match, carry on, lookup gateways */
1061
	if(is_ipaddrv4(lookup_gateway_ip_by_name($gwname)))
1062
		$v4gw = true;
1063
	if(is_ipaddrv6(lookup_gateway_ip_by_name($gwname)))
1064
		$v6gw = true;
1065

    
1066
	$gw_array = return_gateways_array();
1067
	if(is_array($gw_array[$gwname])) {
1068
		switch($gw_array[$gwname]['ipprotocol']) {
1069
			case "inet":
1070
				$v4gw = true;
1071
				break;
1072
			case "inet6":
1073
				$v6gw = true;
1074
				break;
1075
		}
1076
	}
1077

    
1078
	if($v4ip && $v4gw)
1079
		return true;
1080
	if($v6ip && $v6gw)
1081
		return true;
1082

    
1083
	return false;
1084
}
1085

    
1086
/* check if a interface is part of a gateway group */
1087
function interface_gateway_group_member($interface) {
1088
	global $config;
1089

    
1090
	if (is_array($config['gateways']['gateway_group']))
1091
		$groups = $config['gateways']['gateway_group'];
1092
	else
1093
		return false;
1094

    
1095
	$gateways_arr = return_gateways_array(false, true);
1096
	foreach($groups as $group) {
1097
		if(is_array($group['item'])) {
1098
			foreach($group['item'] as $item) {
1099
				$elements = explode("|", $item);
1100
				$gwname = $elements[0];
1101
				if ($interface == $gateways_arr[$gwname]['interface']) {
1102
					unset($gateways_arr);
1103
					return true;
1104
				}
1105
			}
1106
		}
1107
	}
1108
	unset($gateways_arr);
1109

    
1110
	return false;
1111
}
1112

    
1113
function gateway_is_gwgroup_member($name) {
1114
	global $config;
1115

    
1116
	if (is_array($config['gateways']['gateway_group']))
1117
		$groups = $config['gateways']['gateway_group'];
1118
	else
1119
		return false;
1120

    
1121
	$members = array();
1122
	foreach($groups as $group) {
1123
		if (is_array($group['item'])) {
1124
			foreach($group['item'] as $item) {
1125
				$elements = explode("|", $item);
1126
				$gwname = $elements[0];
1127
				if ($name == $elements[0])
1128
					$members[] = $group['name'];
1129
			}
1130
		}
1131
	}
1132

    
1133
	return $members;
1134
}
1135
?>
(25-25/68)