Project

General

Profile

Download (37 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	gwlb.inc
4
	Copyright (C) 2008 Bill Marquette, Seth Mos
5
	Copyright (C) 2010 Ermal Luçi
6
	All rights reserved.
7

    
8
	Redistribution and use in source and binary forms, with or without
9
	modification, are permitted provided that the following conditions are met:
10

    
11
	1. Redistributions of source code must retain the above copyright notice,
12
	this list of conditions and the following disclaimer.
13

    
14
	2. Redistributions in binary form must reproduce the above copyright
15
	notice, this list of conditions and the following disclaimer in the
16
	documentation and/or other materials provided with the distribution.
17

    
18
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
	POSSIBILITY OF SUCH DAMAGE.
28
 */
29

    
30
require_once("config.inc");
31
require_once("rrd.inc");
32

    
33
/* Returns an array of default values used for dpinger */
34
function return_dpinger_defaults() {
35
	return array(
36
		"latencylow" => "200",
37
		"latencyhigh" => "500",
38
		"losslow" => "10",
39
		"losshigh" => "20",
40
		"interval" => "250",
41
		"loss_interval" => "500",
42
		"time_period" => "25000",
43
		"alert_interval" => "1000");
44
}
45

    
46
function running_dpinger_processes() {
47
	global $g;
48

    
49
	$pidfiles = glob("{$g['varrun_path']}/dpinger_*.pid");
50

    
51
	$result = array();
52
	if ($pidfiles === FALSE) {
53
		return $result;
54
	}
55

    
56
	foreach ($pidfiles as $pidfile) {
57
		if (preg_match('/^dpinger_(.+)_([^_]+)_([^_]+)\.pid$/',
58
		    basename($pidfile), $matches)) {
59
			$socket_file = preg_replace('/\.pid$/', '.sock',
60
			    $pidfile);
61
			$result[$matches[1]] = array(
62
			    'srcip'    => $matches[2],
63
			    'targetip' => $matches[3],
64
			    'pidfile'  => $pidfile,
65
			    'socket'   => $socket_file
66
			);
67
			unset($gwinfo);
68
		}
69
	}
70

    
71
	return $result;
72
}
73

    
74
/*
75
 * Stop one or more dpinger process
76
 * default parameter $gwname is '*' that will kill all running sessions
77
 * If a gateway name is passed, only this one will be killed
78
 */
79
function stop_dpinger($gwname = '') {
80
	global $g;
81

    
82
	$running_processes = running_dpinger_processes();
83

    
84
	foreach ($running_processes as $running_gwname => $process) {
85
		if ($gwname != '' && $running_gwname != $gwname) {
86
			continue;
87
		}
88

    
89
		if (isvalidpid($process['pidfile'])) {
90
			killbypid($process['pidfile']);
91
		} else {
92
			@unlink($process['pidfile']);
93
		}
94
	}
95
}
96

    
97
function start_dpinger($gateway) {
98
	global $g;
99

    
100
	if (!isset($gateway['gwifip'])) {
101
		return;
102
	}
103

    
104
	$dpinger_defaults = return_dpinger_defaults();
105

    
106
	$pidfile = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
107
	    "{$gateway['gwifip']}_{$gateway['monitor']}.pid";
108
	$socket = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
109
	    "{$gateway['gwifip']}_{$gateway['monitor']}.sock";
110
	$alarm_cmd = "{$g['etc_path']}/rc.gateway_alarm";
111

    
112
	$params  = "-S ";			/* Log warnings via syslog */
113
	$params  = "-r 0 ";			/* Disable unused reporting thread */
114
	$params .= "-i {$gateway['name']} ";	/* Identifier */
115
	$params .= "-B {$gateway['gwifip']} ";	/* Bind src address */
116
	$params .= "-p {$pidfile} ";		/* PID filename */
117
	$params .= "-u {$socket} ";		/* Status Socket */
118
	$params .= "-C \"{$alarm_cmd}\" ";	/* Command to run on alarm */
119

    
120
	$params .= "-s " .
121
	    (isset($gateway['interval']) && is_numeric($gateway['interval'])
122
	    ? $gateway['interval']
123
	    : $dpinger_defaults['interval']
124
	    ) . " ";
125

    
126
	$params .= "-l " .
127
	    (isset($gateway['loss_interval']) && is_numeric($gateway['loss_interval'])
128
	    ?  $gateway['loss_interval']
129
	    : $dpinger_defaults['loss_interval']
130
	    ) . " ";
131

    
132
	$params .= "-t " .
133
	    (isset($gateway['time_period']) && is_numeric($gateway['time_period'])
134
	    ?  $gateway['time_period']
135
	    : $dpinger_defaults['time_period']
136
	    ) . " ";
137

    
138
	$params .= "-A " .
139
	    (isset($gateway['alert_interval']) && is_numeric($gateway['alert_interval'])
140
	    ?  $gateway['alert_interval']
141
	    : $dpinger_defaults['alert_interval']
142
	    ) . " ";
143

    
144
	$params .= "-D " .
145
	    (isset($gateway['latencyhigh']) && is_numeric($gateway['latencyhigh'])
146
	    ?  $gateway['latencyhigh']
147
	    : $dpinger_defaults['latencyhigh']
148
	    ) . " ";
149

    
150
	$params .= "-L " .
151
	    (isset($gateway['losshigh']) && is_numeric($gateway['losshigh'])
152
	    ?  $gateway['losshigh']
153
	    : $dpinger_defaults['losshigh']
154
	    ) . " ";
155

    
156
	mwexec_bg("/usr/local/bin/dpinger {$params} {$gateway['monitor']}");
157
}
158

    
159
/*
160
 * Starts dpinger processes and adds appropriate static routes for monitor IPs
161
 */
162
function setup_gateways_monitor() {
163
	global $config, $g;
164

    
165
	$gateways_arr = return_gateways_array();
166
	if (!is_array($gateways_arr)) {
167
		log_error("No gateways to monitor. dpinger will not run.");
168
		stop_dpinger();
169
		return;
170
	}
171

    
172
	$monitor_ips = array();
173
	foreach ($gateways_arr as $gwname => $gateway) {
174
		/* Do not monitor if such was requested */
175
		if (isset($gateway['monitor_disable'])) {
176
			continue;
177
		}
178
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
179
			if (is_ipaddr($gateway['gateway'])) {
180
				$gateway['monitor'] = $gateway['gateway'];
181
			} else { /* No chance to get an ip to monitor skip target. */
182
				continue;
183
			}
184
		}
185

    
186
		/* if the monitor address is already used before, skip */
187
		if (in_array($gateway['monitor'], $monitor_ips)) {
188
			continue;
189
		}
190

    
191
		/* Interface ip is needed since dpinger will bind a socket to it.
192
		 * However the config GUI should already have checked this and when
193
		 * PPPoE is used the IP address is set to "dynamic". So using is_ipaddrv4
194
		 * or is_ipaddrv6 to identify packet type would be wrong, especially as
195
		 * further checks (that can cope with the "dynamic" case) are present inside
196
		 * the if block. So using $gateway['ipprotocol'] is the better option.
197
		 */
198
		if ($gateway['ipprotocol'] == "inet") { // This is an IPv4 gateway...
199
			$gwifip = find_interface_ip($gateway['interface'], true);
200
			if (!is_ipaddrv4($gwifip)) {
201
				continue; //Skip this target
202
			}
203

    
204
			if ($gwifip == "0.0.0.0") {
205
				continue; //Skip this target - the gateway is still waiting for DHCP
206
			}
207

    
208
			/*
209
			 * If the gateway is the same as the monitor we do not add a
210
			 * route as this will break the routing table.
211
			 * Add static routes for each gateway with their monitor IP
212
			 * not strictly necessary but is a added level of protection.
213
			 */
214
			if (is_ipaddrv4($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
215
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
216
				if (interface_isppp_type($gateway['friendlyiface'])) {
217
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
218
						" -iface " . escapeshellarg($gateway['interface']), true);
219
				} else {
220
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
221
						" " . escapeshellarg($gateway['gateway']), true);
222
				}
223

    
224
				pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp");
225
			}
226
		} else if ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway...
227
			if ($gateway['monitor'] == $gateway['gateway']) {
228
				/* link locals really need a different src ip */
229
				if (is_linklocal($gateway['gateway'])) {
230
					if (!strpos($gateway['gateway'], '%')) {
231
						$gateway['gateway'] .= '%' . $gateway['interface'];
232
					}
233
					$gwifip = find_interface_ipv6_ll($gateway['interface'], true);
234
				} else {
235
					$gwifip = find_interface_ipv6($gateway['interface'], true);
236
				}
237
			} else {
238
				/* 'monitor' has been set, so makes sure it has precedence over
239
				 * 'gateway' in defining the source IP. Otherwise if 'gateway'
240
				 * is a local link and 'monitor' is global routable then the
241
				 * ICMP6 response would not find its way back home...
242
				 */
243
				$gwifip = find_interface_ipv6($gateway['interface'], true);
244
			}
245

    
246
			/* Make sure srcip and target have scope defined when they are ll */
247
			if (is_linklocal($gwifip) && !strpos($gwifip, '%')) {
248
				$gwifip .= '%' . $gateway['interface'];
249
			}
250
			if (is_linklocal($gateway['monitor']) && !strpos($gateway['monitor'], '%')) {
251
				$gateway['monitor'] .= "%{$gateway['interface']}";
252
			}
253

    
254
			if (!is_ipaddrv6($gwifip)) {
255
				continue; //Skip this target
256
			}
257

    
258
			/*
259
			 * If the gateway is the same as the monitor we do not add a
260
			 * route as this will break the routing table.
261
			 * Add static routes for each gateway with their monitor IP
262
			 * not strictly necessary but is a added level of protection.
263
			 */
264
			if ($gateway['gateway'] != $gateway['monitor']) {
265
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
266
				if (interface_isppp_type($gateway['friendlyiface'])) {
267
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
268
						" -iface " . escapeshellarg($gateway['interface']), true);
269
				} else {
270
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
271
						" " . escapeshellarg($gateway['gateway']), true);
272
				}
273

    
274
				pfSense_kill_states("::0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmpv6");
275
			}
276
		} else {
277
			continue;
278
		}
279

    
280
		$monitor_ips[] = $gateway['monitor'];
281
		$gateways_arr[$gwname]['enable_dpinger'] = true;
282
		$gateways_arr[$gwname]['gwifip'] = $gwifip;
283
	}
284

    
285
	stop_dpinger();
286

    
287
	/* Start new processes */
288
	foreach ($gateways_arr as $gateway) {
289
		if (isset($gateway['enable_dpinger'])) {
290
			start_dpinger($gateway);
291
		}
292
	}
293

    
294
	return 0;
295
}
296

    
297
function get_dpinger_status($gwname) {
298
	global $g;
299

    
300
	$running_processes = running_dpinger_processes();
301

    
302
	if (!isset($running_processes[$gwname])) {
303
		log_error("dpinger: No dpinger session running for gateway {$gwname}");
304
		return false;
305
	}
306

    
307
	$proc = $running_processes[$gwname];
308
	unset($running_processes);
309

    
310
	if (!file_exists($proc['socket'])) {
311
		log_error("dpinger: status socket {$proc['socket']} not found");
312
		return false;
313
	}
314

    
315
	$fp = stream_socket_client("unix://{$proc['socket']}", $errno, $errstr, 10);
316
	if (!$fp) {
317
		log_error("dpinger: cannot connect to status socket {$proc['socket']} - $errstr ($errno)");
318
		return false;
319
	}
320

    
321
	$status = '';
322
	while (!feof($fp)) {
323
		$status .= fgets($fp, 1024);
324
	}
325
	fclose($fp);
326

    
327
	$r = array();
328
	list(
329
	    $r['gwname'],
330
	    $r['latency_avg'],
331
	    $r['latency_stddev'],
332
	    $r['loss']
333
	) = explode(' ', preg_replace('/\n/', '', $status));
334

    
335
	$r['srcip'] = $proc['srcip'];
336
	$r['targetip'] = $proc['targetip'];
337

    
338
	$gateways_arr = return_gateways_array();
339
	unset($gw);
340
	if (isset($gateways_arr[$gwname])) {
341
		$gw = $gateways_arr[$gwname];
342
	}
343

    
344
	$r['latency_avg'] = round($r['latency_avg']/1000, 3);
345
	$r['latency_stddev'] = round($r['latency_stddev']/1000, 3);
346

    
347
	$r['status'] = "none";
348
	if (isset($gw) && isset($gw['force_down'])) {
349
		$r['status'] = "force_down";
350
	} else if (isset($gw)) {
351
		$settings = return_dpinger_defaults();
352

    
353
		$keys = array(
354
		    'latencylow',
355
		    'latencyhigh',
356
		    'losslow',
357
		    'losshigh'
358
		);
359

    
360
		/* Replace default values by user-defined */
361
		foreach ($keys as $key) {
362
			if (isset($gw[$key]) && is_numeric($gw[$key])) {
363
				$settings[$key] = $gw[$key];
364
			}
365
		}
366

    
367
		if ($r['latency_avg'] > $settings['latencyhigh'] ||
368
		    $r['loss'] > $settings['losshigh']) {
369
			$r['status'] = "down";
370
		} else if ($r['latency_avg'] > $settings['latencylow']) {
371
			$r['status'] = "delay";
372
		} else if ($r['loss'] > $settings['losslow']) {
373
			$r['status'] = "loss";
374
		}
375
	}
376

    
377
	return $r;
378
}
379

    
380
/* return the status of the dpinger targets as an array */
381
function return_gateways_status($byname = false) {
382
	global $config, $g;
383

    
384
	$dpinger_gws = running_dpinger_processes();
385
	$status = array();
386

    
387
	$gateways_arr = return_gateways_array();
388

    
389
	foreach ($dpinger_gws as $gwname => $gwdata) {
390
		$dpinger_status = get_dpinger_status($gwname);
391
		if ($dpinger_status === false) {
392
			continue;
393
		}
394

    
395
		if ($byname == false) {
396
			$target = $dpinger_status['targetip'];
397
		} else {
398
			$target = $gwname;
399
		}
400

    
401
		$status[$target] = array();
402
		$status[$target]['monitorip'] = $dpinger_status['targetip'];
403
		$status[$target]['srcip'] = $dpinger_status['srcip'];
404
		$status[$target]['name'] = $gwname;
405
		$status[$target]['delay'] = empty($dpinger_status['latency_avg']) ? "0ms" : $dpinger_status['latency_avg'] . "ms";
406
		$status[$target]['loss'] = empty($dpinger_status['loss']) ? "0.0%" : round($dpinger_status['loss'], 1) . "%";
407
		$status[$target]['status'] = $dpinger_status['status'];
408
	}
409

    
410
	/* tack on any gateways that have monitoring disabled
411
	 * or are down, which could cause gateway groups to fail */
412
	$gateways_arr = return_gateways_array();
413
	foreach ($gateways_arr as $gwitem) {
414
		if (!isset($gwitem['monitor_disable'])) {
415
			continue;
416
		}
417
		if (!is_ipaddr($gwitem['monitor'])) {
418
			$realif = $gwitem['interface'];
419
			$tgtip = get_interface_gateway($realif);
420
			if (!is_ipaddr($tgtip)) {
421
				$tgtip = "none";
422
			}
423
			$srcip = find_interface_ip($realif);
424
		} else {
425
			$tgtip = $gwitem['monitor'];
426
			$srcip = find_interface_ip($realif);
427
		}
428
		if ($byname == true) {
429
			$target = $gwitem['name'];
430
		} else {
431
			$target = $tgtip;
432
		}
433

    
434
		/* failsafe for down interfaces */
435
		if ($target == "none") {
436
			$target = $gwitem['name'];
437
			$status[$target]['name'] = $gwitem['name'];
438
			$status[$target]['delay'] = "0.0ms";
439
			$status[$target]['loss'] = "100.0%";
440
			$status[$target]['status'] = "down";
441
		} else {
442
			$status[$target]['monitorip'] = $tgtip;
443
			$status[$target]['srcip'] = $srcip;
444
			$status[$target]['name'] = $gwitem['name'];
445
			$status[$target]['delay'] = "0.0ms";
446
			$status[$target]['loss'] = "0.0%";
447
			$status[$target]['status'] = "none";
448
		}
449
	}
450
	return($status);
451
}
452

    
453
/* Return all configured gateways on the system */
454
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
455
	global $config, $g;
456

    
457
	$gateways_arr = array();
458
	$gateways_arr_temp = array();
459

    
460
	$found_defaultv4 = 0;
461
	$found_defaultv6 = 0;
462

    
463
	// Ensure the interface cache is up to date first
464
	$interfaces = get_interface_arr(true);
465
	$interfaces_v4 = array();
466
	$interfaces_v6 = array();
467

    
468
	$i = -1;
469
	/* Process/add all the configured gateways. */
470
	if (is_array($config['gateways']['gateway_item'])) {
471
		foreach ($config['gateways']['gateway_item'] as $gateway) {
472
			/* Increment it here to do not skip items */
473
			$i++;
474

    
475
			if (empty($config['interfaces'][$gateway['interface']])) {
476
				if ($inactive === false) {
477
					continue;
478
				} else {
479
					$gateway['inactive'] = true;
480
				}
481
			}
482
			$wancfg = $config['interfaces'][$gateway['interface']];
483

    
484
			/* skip disabled interfaces */
485
			if ($disabled === false && (!isset($wancfg['enable']))) {
486
				continue;
487
			}
488

    
489
			/* if the gateway is dynamic and we can find the IPv4, Great! */
490
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
491
				if ($gateway['ipprotocol'] == "inet") {
492
					/* we know which interfaces is dynamic, this should be made a function */
493
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
494
					/* no IP address found, set to dynamic */
495
					if (!is_ipaddrv4($gateway['gateway'])) {
496
						$gateway['gateway'] = "dynamic";
497
					}
498
					$gateway['dynamic'] = true;
499
				}
500

    
501
				/* if the gateway is dynamic and we can find the IPv6, Great! */
502
				else if ($gateway['ipprotocol'] == "inet6") {
503
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
504
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
505
					/* no IPv6 address found, set to dynamic */
506
					if (!is_ipaddrv6($gateway['gateway'])) {
507
						$gateway['gateway'] = "dynamic";
508
					}
509
					$gateway['dynamic'] = true;
510
				}
511
			} else {
512
				/* getting this detection right is hard at this point because we still don't
513
				 * store the address family in the gateway item */
514
				if (is_ipaddrv4($gateway['gateway'])) {
515
					$gateway['ipprotocol'] = "inet";
516
				} else if (is_ipaddrv6($gateway['gateway'])) {
517
					$gateway['ipprotocol'] = "inet6";
518
				}
519
			}
520

    
521
			if (isset($gateway['monitor_disable'])) {
522
				$gateway['monitor_disable'] = true;
523
			} else if (empty($gateway['monitor'])) {
524
				$gateway['monitor'] = $gateway['gateway'];
525
			}
526

    
527
			$gateway['friendlyiface'] = $gateway['interface'];
528

    
529
			/* special treatment for tunnel interfaces */
530
			if ($gateway['ipprotocol'] == "inet6") {
531
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
532
				$interfaces_v6[$gateway['friendlyiface']] = $gateway['friendlyiface'];
533
			} else {
534
				$gateway['interface'] = get_real_interface($gateway['interface'], "all", false, false);
535
				$interfaces_v4[$gateway['friendlyiface']] = $gateway['friendlyiface'];
536
			}
537

    
538
			/* entry has a default flag, use it */
539
			if (isset($gateway['defaultgw'])) {
540
				if ($gateway['ipprotocol'] == "inet") {
541
					$gateway['defaultgw'] = true;
542
					$found_defaultv4 = 1;
543
				} else if ($gateway['ipprotocol'] == "inet6") {
544
					$gateway['defaultgw'] = true;
545
					$found_defaultv6 = 1;
546
				}
547
			}
548
			/* include the gateway index as the attribute */
549
			$gateway['attribute'] = $i;
550

    
551
			/* Remember all the gateway names, even ones to be skipped because they are disabled. */
552
			/* Then we can easily know and match them later when attempting to add dynamic gateways to the list. */
553
			$gateways_arr_temp[$gateway['name']] = $gateway;
554

    
555
			/* skip disabled gateways if the caller has not asked for them to be returned. */
556
			if (!($disabled === false && isset($gateway['disabled']))) {
557
				$gateways_arr[$gateway['name']] = $gateway;
558
			}
559
		}
560
	}
561
	unset($gateway);
562

    
563
	/* Loop through all interfaces with a gateway and add it to a array */
564
	if ($disabled == false) {
565
		$iflist = get_configured_interface_with_descr();
566
	} else {
567
		$iflist = get_configured_interface_with_descr(false, true);
568
	}
569

    
570
	/* Process/add dynamic v4 gateways. */
571
	foreach ($iflist as $ifname => $friendly) {
572
		if (!interface_has_gateway($ifname)) {
573
			continue;
574
		}
575

    
576
		if (empty($config['interfaces'][$ifname])) {
577
			continue;
578
		}
579

    
580
		$ifcfg = &$config['interfaces'][$ifname];
581
		if (!isset($ifcfg['enable'])) {
582
			continue;
583
		}
584

    
585
		if (!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr'])) {
586
			continue;
587
		}
588

    
589
		if (isset($interfaces_v4[$ifname])) {
590
			continue;
591
		}
592

    
593
		$ctype = "";
594
		switch ($ifcfg['ipaddr']) {
595
			case "dhcp":
596
			case "pppoe":
597
			case "pptp":
598
			case "ppp":
599
				$ctype = strtoupper($ifcfg['ipaddr']);
600
				break;
601
			default:
602
				$tunnelif = substr($ifcfg['if'], 0, 3);
603
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
604
					// if current iface is an ovpn server endpoint then check its type, skip tap only
605
					if (substr($ifcfg['if'], 4, 1) == 's') {
606
						$ovpnid = substr($ifcfg['if'], 5);
607
						if (is_array($config['openvpn']['openvpn-server'])) {
608
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
609
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
610
									if ($ovpnserverconf['dev_mode'] == "tap") {
611
										continue 3;
612
									}
613
								}
614
							}
615
						}
616
					}
617
					$ctype = "VPNv4";
618
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
619
					$ctype = "TUNNELv4";
620
				}
621
				break;
622
		}
623
		$ctype = "_". strtoupper($ctype);
624

    
625
		$gateway = array();
626
		$gateway['dynamic'] = false;
627
		$gateway['ipprotocol'] = "inet";
628
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
629
		$gateway['interface'] = get_real_interface($ifname);
630
		$gateway['friendlyiface'] = $ifname;
631
		$gateway['name'] = "{$friendly}{$ctype}";
632
		$gateway['attribute'] = "system";
633

    
634
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
635
			$gateway['defaultgw'] = true;
636
			$gateway['dynamic'] = true;
637
			$found_defaultv4 = 1;
638
		}
639
		/* Loopback dummy for dynamic interfaces without a IP */
640
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true) {
641
			$gateway['gateway'] = "dynamic";
642
		}
643

    
644
		/* automatically skip known static and dynamic gateways that were previously processed */
645
		foreach ($gateways_arr_temp as $gateway_item) {
646
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
647
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
648
				continue 2;
649
			}
650
		}
651

    
652
		if (is_ipaddrv4($gateway['gateway'])) {
653
			$gateway['monitor'] = $gateway['gateway'];
654
		}
655

    
656
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
657
		$gateways_arr[$gateway['name']] = $gateway;
658
	}
659
	unset($gateway);
660

    
661
	/* Process/add dynamic v6 gateways. */
662
	foreach ($iflist as $ifname => $friendly) {
663
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
664
		if (!isset($config['system']['ipv6allow'])) {
665
			break;
666
		}
667

    
668
		if (!interface_has_gatewayv6($ifname)) {
669
			continue;
670
		}
671

    
672
		if (empty($config['interfaces'][$ifname])) {
673
			continue;
674
		}
675

    
676
		$ifcfg = &$config['interfaces'][$ifname];
677
		if (!isset($ifcfg['enable'])) {
678
			continue;
679
		}
680

    
681
		if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
682
			continue;
683
		}
684

    
685
		if (isset($interfaces_v6[$ifname])) {
686
			continue;
687
		}
688

    
689
		$ctype = "";
690
		switch ($ifcfg['ipaddrv6']) {
691
			case "slaac":
692
			case "dhcp6":
693
			case "6to4":
694
			case "6rd":
695
				$ctype = strtoupper($ifcfg['ipaddrv6']);
696
				break;
697
			default:
698
				$tunnelif = substr($ifcfg['if'], 0, 3);
699
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
700
					// if current iface is an ovpn server endpoint then check its type, skip tap only
701
					if (substr($ifcfg['if'], 4, 1) == 's') {
702
						$ovpnid = substr($ifcfg['if'], 5);
703
						if (is_array($config['openvpn']['openvpn-server'])) {
704
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
705
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
706
									if ($ovpnserverconf['dev_mode'] == "tap") {
707
										continue 3;
708
									}
709
								}
710
							}
711
						}
712
					}
713
					$ctype = "VPNv6";
714
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
715
					$ctype = "TUNNELv6";
716
				}
717
				break;
718
		}
719
		$ctype = "_". strtoupper($ctype);
720

    
721
		$gateway = array();
722
		$gateway['dynamic'] = false;
723
		$gateway['ipprotocol'] = "inet6";
724
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
725
		$gateway['interface'] = get_real_interface($ifname, "inet6");
726
		switch ($ifcfg['ipaddrv6']) {
727
			case "6rd":
728
			case "6to4":
729
				$gateway['dynamic'] = "default";
730
				break;
731
		}
732
		$gateway['friendlyiface'] = $ifname;
733
		$gateway['name'] = "{$friendly}{$ctype}";
734
		$gateway['attribute'] = "system";
735

    
736
		if (($gateway['dynamic'] === "default") && ($found_defaultv6 == 0)) {
737
			$gateway['defaultgw'] = true;
738
			$gateway['dynamic'] = true;
739
			$found_defaultv6 = 1;
740
		}
741

    
742
		/* Loopback dummy for dynamic interfaces without a IP */
743
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true) {
744
			$gateway['gateway'] = "dynamic";
745
		}
746

    
747
		/* automatically skip known static and dynamic gateways that were previously processed */
748
		foreach ($gateways_arr_temp as $gateway_item) {
749
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
750
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
751
				continue 2;
752
			}
753
		}
754

    
755
		if (is_ipaddrv6($gateway['gateway'])) {
756
			$gateway['monitor'] = $gateway['gateway'];
757
		}
758

    
759
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
760
		$gateways_arr[$gateway['name']] = $gateway;
761
	}
762
	unset($gateway);
763

    
764
	/* FIXME: Should this be enabled.
765
	 * Some interface like wan might be default but have no info recorded
766
	 * the config. */
767
	/* this is a fallback if all else fails and we want to get packets out @smos */
768
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
769
		foreach ($gateways_arr as &$gateway) {
770
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
771
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
772
					$gateway['defaultgw'] = true;
773
					$found_defaultv4 = 1;
774
				}
775
			}
776
			else if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
777
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
778
					$gateway['defaultgw'] = true;
779
					$found_defaultv6 = 1;
780
				}
781
			}
782
		}
783
	}
784

    
785
	if ($localhost === true) {
786
		/* attach localhost for Null routes */
787
		$gwlo4 = array();
788
		$gwlo4['name'] = "Null4";
789
		$gwlo4['interface'] = "lo0";
790
		$gwlo4['ipprotocol'] = "inet";
791
		$gwlo4['gateway'] = "127.0.0.1";
792
		$gwlo6 = array();
793
		$gwlo6['name'] = "Null6";
794
		$gwlo6['interface'] = "lo0";
795
		$gwlo6['ipprotocol'] = "inet6";
796
		$gwlo6['gateway'] = "::1";
797
		$gateways_arr['Null4'] = $gwlo4;
798
		$gateways_arr['Null6'] = $gwlo6;
799
	}
800
	return($gateways_arr);
801
}
802

    
803
function fixup_default_gateway($ipprotocol, $gateways_status, $gateways_arr) {
804
	global $config, $g;
805
	/*
806
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
807
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
808
	 */
809
	$upgw = '';
810
	$dfltgwname = '';
811
	$dfltgwdown = false;
812
	$dfltgwfound = false;
813
	foreach ($gateways_arr as $gwname => $gwsttng) {
814
		if (($gwsttng['ipprotocol'] == $ipprotocol) && isset($gwsttng['defaultgw'])) {
815
			$dfltgwfound = true;
816
			$dfltgwname = $gwname;
817
			if (!isset($gwsttng['monitor_disable']) && $gateways_status[$gwname]['status'] != "none") {
818
				$dfltgwdown = true;
819
			}
820
		}
821
		/* Keep a record of the last up gateway */
822
		/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
823
		if (empty($upgw) && ($gwsttng['ipprotocol'] == $ipprotocol) && (isset($gwsttng['monitor_disable']) || $gateways_status[$gwname]['status'] == "none") && $gwsttng[$gwname]['friendlyiface'] != "lan") {
824
			$upgw = $gwname;
825
		}
826
		if ($dfltgwdown == true && !empty($upgw)) {
827
			break;
828
		}
829
	}
830
	if ($dfltgwfound == false) {
831
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
832
		if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down")) {
833
			$dfltgwdown = true;
834
		}
835
	}
836
	if ($dfltgwdown == true && !empty($upgw)) {
837
		if ($gateways_arr[$upgw]['gateway'] == "dynamic") {
838
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
839
		}
840
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
841
			log_error("Default gateway down setting {$upgw} as default!");
842
			if (is_ipaddrv6($gateways_arr[$upgw]['gateway'])) {
843
				$inetfamily = "-inet6";
844
			} else {
845
				$inetfamily = "-inet";
846
			}
847
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
848
		}
849
	} else if (!empty($dfltgwname)) {
850
		$defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n");
851
		if ($ipprotocol == 'inet6' && !is_ipaddrv6($gateways_arr[$dfltgwname]['gateway'])) {
852
			return;
853
		}
854
		if ($ipprotocol == 'inet' && !is_ipaddrv4($gateways_arr[$dfltgwname]['gateway'])) {
855
			return;
856
		}
857
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway']) {
858
			mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}");
859
		}
860
	}
861
}
862

    
863
/*
864
 * Return an array with all gateway groups with name as key
865
 * All gateway groups will be processed before returning the array.
866
 */
867
function return_gateway_groups_array() {
868
	global $config, $g;
869

    
870
	/* fetch the current gateways status */
871
	$gateways_status = return_gateways_status(true);
872
	$gateways_arr = return_gateways_array();
873
	$gateway_groups_array = array();
874

    
875
	if (isset($config['system']['gw_switch_default'])) {
876
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
877
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
878
	}
879
	if (is_array($config['gateways']['gateway_group'])) {
880
		$carplist = get_configured_carp_interface_list();
881
		foreach ($config['gateways']['gateway_group'] as $group) {
882
			/* create array with group gateways members separated by tier */
883
			$tiers = array();
884
			$backupplan = array();
885
			$gwvip_arr = array();
886
			foreach ($group['item'] as $item) {
887
				list($gwname, $tier, $vipname) = explode("|", $item);
888

    
889
				if (is_ipaddr($carplist[$vipname])) {
890
					if (!is_array($gwvip_arr[$group['name']])) {
891
						$gwvip_arr[$group['name']] = array();
892
					}
893
					$gwvip_arr[$group['name']][$gwname] = $vipname;
894
				}
895

    
896
				/* Do it here rather than reiterating again the group in case no member is up. */
897
				if (!is_array($backupplan[$tier])) {
898
					$backupplan[$tier] = array();
899
				}
900
				$backupplan[$tier][] = $gwname;
901

    
902
				/* check if the gateway is available before adding it to the array */
903
				if (is_array($gateways_status[$gwname])) {
904
					$status = $gateways_status[$gwname];
905
					$gwdown = false;
906
					if (stristr($status['status'], "down")) {
907
						$msg = sprintf(gettext("MONITOR: %s is down, omitting from routing group {$group['name']}"), $gwname);
908
						$gwdown = true;
909
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
910
						/* packet loss */
911
						$msg = sprintf(gettext("MONITOR: %s has packet loss, omitting from routing group {$group['name']}"), $gwname);
912
						$gwdown = true;
913
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
914
						/* high latency */
915
						$msg = sprintf(gettext("MONITOR: %s has high latency, omitting from routing group {$group['name']}"), $gwname);
916
						$gwdown = true;
917
					}
918
					if ($gwdown == true) {
919
						log_error($msg);
920
						notify_via_growl($msg);
921
						notify_via_smtp($msg);
922
					} else {
923
						/* Online add member */
924
						if (!is_array($tiers[$tier])) {
925
							$tiers[$tier] = array();
926
						}
927
						$tiers[$tier][] = $gwname;
928
					}
929
				} else if (isset($gateways_arr[$gwname]['monitor_disable'])) {
930
					$tiers[$tier][] = $gwname;
931
				}
932
			}
933
			$tiers_count = count($tiers);
934
			if ($tiers_count == 0) {
935
				/* Oh dear, we have no members! Engage Plan B */
936
				if (!platform_booting()) {
937
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
938
					log_error($msg);
939
					notify_via_growl($msg);
940
					//notify_via_smtp($msg);
941
				}
942
				$tiers = $backupplan;
943
			}
944
			/* sort the tiers array by the tier key */
945
			ksort($tiers);
946

    
947
			/* we do not really foreach the tiers as we stop after the first tier */
948
			foreach ($tiers as $tieridx => $tier) {
949
				/* process all gateways in this tier */
950
				foreach ($tier as $member) {
951
					/* determine interface gateway */
952
					if (isset($gateways_arr[$member])) {
953
						$gateway = $gateways_arr[$member];
954
						$int = $gateway['interface'];
955
						$gatewayip = "";
956
						if (is_ipaddr($gateway['gateway'])) {
957
							$gatewayip = $gateway['gateway'];
958
						} else if (!empty($int)) {
959
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
960
						}
961

    
962
						if (!empty($int)) {
963
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
964
							if (is_ipaddr($gatewayip)) {
965
								$groupmember = array();
966
								$groupmember['int'] = $int;
967
								$groupmember['gwip'] = $gatewayip;
968
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
969
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member])) {
970
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
971
								}
972
								$gateway_groups_array[$group['name']][] = $groupmember;
973
							}
974
						}
975
					}
976
				}
977
				/* we should have the 1st available tier now, exit stage left */
978
				if (count($gateway_groups_array[$group['name']]) > 0) {
979
					break;
980
				} else {
981
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
982
				}
983
			}
984
		}
985
	}
986

    
987
	return ($gateway_groups_array);
988
}
989

    
990
/* Update DHCP WAN Interface ip address in gateway group item */
991
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
992
	global $config, $g;
993
	foreach ($config['gateways']['gateway_item'] as & $gw) {
994
		if ($gw['interface'] == $interface) {
995
			$current_gw = get_interface_gateway($interface);
996
			if ($gw['gateway'] <> $current_gw) {
997
				$gw['gateway'] = $current_gw;
998
				$changed = true;
999
			}
1000
		}
1001
	}
1002
	if ($changed && $current_gw) {
1003
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
1004
	}
1005
}
1006

    
1007
function lookup_gateway_ip_by_name($name, $disabled = false) {
1008

    
1009
	$gateways_arr = return_gateways_array($disabled, true);
1010
	foreach ($gateways_arr as $gname => $gw) {
1011
		if ($gw['name'] === $name || $gname === $name) {
1012
			return $gw['gateway'];
1013
		}
1014
	}
1015

    
1016
	return false;
1017
}
1018

    
1019
function lookup_gateway_monitor_ip_by_name($name) {
1020

    
1021
	$gateways_arr = return_gateways_array(false, true);
1022
	if (!empty($gateways_arr[$name])) {
1023
		$gateway = $gateways_arr[$name];
1024
		if (!is_ipaddr($gateway['monitor'])) {
1025
			return $gateway['gateway'];
1026
		}
1027

    
1028
		return $gateway['monitor'];
1029
	}
1030

    
1031
	return (false);
1032
}
1033

    
1034
function lookup_gateway_interface_by_name($name) {
1035

    
1036
	$gateways_arr = return_gateways_array(false, true);
1037
	if (!empty($gateways_arr[$name])) {
1038
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
1039
		return ($interfacegw);
1040
	}
1041

    
1042
	return (false);
1043
}
1044

    
1045
function get_interface_gateway($interface, &$dynamic = false) {
1046
	global $config, $g;
1047

    
1048
	if (substr($interface, 0, 4) == '_vip') {
1049
		$interface = get_configured_carp_interface_list($interface, 'inet', 'iface');
1050
	}
1051

    
1052
	$gw = NULL;
1053
	$gwcfg = $config['interfaces'][$interface];
1054
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
1055
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1056
			if (($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
1057
				$gw = $gateway['gateway'];
1058
				break;
1059
			}
1060
		}
1061
	}
1062

    
1063
	// for dynamic interfaces we handle them through the $interface_router file.
1064
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
1065
		$realif = get_real_interface($interface);
1066
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
1067
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
1068
			$dynamic = true;
1069
		}
1070
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw")) {
1071
			$dynamic = "default";
1072
		}
1073

    
1074
	}
1075

    
1076
	/* return gateway */
1077
	return ($gw);
1078
}
1079

    
1080
function get_interface_gateway_v6($interface, &$dynamic = false) {
1081
	global $config, $g;
1082

    
1083
	if (substr($interface, 0, 4) == '_vip') {
1084
		$interface = get_configured_carp_interface_list($interface, 'inet6', 'iface');
1085
	}
1086

    
1087
	$gw = NULL;
1088
	$gwcfg = $config['interfaces'][$interface];
1089
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1090
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1091
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1092
				$gw = $gateway['gateway'];
1093
				break;
1094
			}
1095
		}
1096
	}
1097

    
1098
	// for dynamic interfaces we handle them through the $interface_router file.
1099
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1100
		$realif = get_real_interface($interface);
1101
		if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1102
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1103
			$dynamic = true;
1104
		}
1105
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6")) {
1106
			$dynamic = "default";
1107
		}
1108
	}
1109
	/* return gateway */
1110
	return ($gw);
1111
}
1112

    
1113
/* Check a IP address against a gateway IP or name
1114
 * to verify it's address family */
1115
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1116
	$v4ip = false;
1117
	$v6ip = false;
1118
	$v4gw = false;
1119
	$v6gw = false;
1120

    
1121
	if (is_ipaddrv4($ipaddr)) {
1122
		$v4ip = true;
1123
	}
1124
	if (is_ipaddrv6($ipaddr)) {
1125
		$v6ip = true;
1126
	}
1127
	if (is_ipaddrv4($gwname)) {
1128
		$v4gw = true;
1129
	}
1130
	if (is_ipaddrv6($gwname)) {
1131
		$v6gw = true;
1132
	}
1133

    
1134
	if ($v4ip && $v4gw) {
1135
		return true;
1136
	}
1137
	if ($v6ip && $v6gw) {
1138
		return true;
1139
	}
1140

    
1141
	/* still no match, carry on, lookup gateways */
1142
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1143
		$v4gw = true;
1144
	}
1145
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1146
		$v6gw = true;
1147
	}
1148

    
1149
	$gw_array = return_gateways_array();
1150
	if (is_array($gw_array[$gwname])) {
1151
		switch ($gw_array[$gwname]['ipprotocol']) {
1152
			case "inet":
1153
				$v4gw = true;
1154
				break;
1155
			case "inet6":
1156
				$v6gw = true;
1157
				break;
1158
		}
1159
	}
1160

    
1161
	if ($v4ip && $v4gw) {
1162
		return true;
1163
	}
1164
	if ($v6ip && $v6gw) {
1165
		return true;
1166
	}
1167

    
1168
	return false;
1169
}
1170

    
1171
/* check if a interface is part of a gateway group */
1172
function interface_gateway_group_member($interface) {
1173
	global $config;
1174

    
1175
	if (is_array($config['gateways']['gateway_group'])) {
1176
		$groups = $config['gateways']['gateway_group'];
1177
	} else {
1178
		return false;
1179
	}
1180

    
1181
	$gateways_arr = return_gateways_array(false, true);
1182
	foreach ($groups as $group) {
1183
		if (is_array($group['item'])) {
1184
			foreach ($group['item'] as $item) {
1185
				$elements = explode("|", $item);
1186
				$gwname = $elements[0];
1187
				if ($interface == $gateways_arr[$gwname]['interface']) {
1188
					unset($gateways_arr);
1189
					return true;
1190
				}
1191
			}
1192
		}
1193
	}
1194
	unset($gateways_arr);
1195

    
1196
	return false;
1197
}
1198

    
1199
function gateway_is_gwgroup_member($name) {
1200
	global $config;
1201

    
1202
	if (is_array($config['gateways']['gateway_group'])) {
1203
		$groups = $config['gateways']['gateway_group'];
1204
	} else {
1205
		return false;
1206
	}
1207

    
1208
	$members = array();
1209
	foreach ($groups as $group) {
1210
		if (is_array($group['item'])) {
1211
			foreach ($group['item'] as $item) {
1212
				$elements = explode("|", $item);
1213
				$gwname = $elements[0];
1214
				if ($name == $elements[0]) {
1215
					$members[] = $group['name'];
1216
				}
1217
			}
1218
		}
1219
	}
1220

    
1221
	return $members;
1222
}
1223
?>
(24-24/65)