Project

General

Profile

Download (36.9 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 .= "-i {$gateway['name']} ";	/* Identifier */
114
	$params .= "-B {$gateway['gwifip']} ";	/* Bind src address */
115
	$params .= "-p {$pidfile} ";		/* PID filename */
116
	$params .= "-u {$socket} ";		/* Status Socket */
117
	$params .= "-C \"{$alarm_cmd}\" ";	/* Command to run on alarm */
118

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
284
	stop_dpinger();
285

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

    
293
	return 0;
294
}
295

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

    
299
	$running_processes = running_dpinger_processes();
300

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

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

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

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

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

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

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

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

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

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

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

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

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

    
376
	return $r;
377
}
378

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

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

    
386
	$gateways_arr = return_gateways_array();
387

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
986
	return ($gateway_groups_array);
987
}
988

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

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

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

    
1015
	return false;
1016
}
1017

    
1018
function lookup_gateway_monitor_ip_by_name($name) {
1019

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

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

    
1030
	return (false);
1031
}
1032

    
1033
function lookup_gateway_interface_by_name($name) {
1034

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

    
1041
	return (false);
1042
}
1043

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

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

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

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

    
1073
	}
1074

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

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

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

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

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

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

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

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

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

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

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

    
1167
	return false;
1168
}
1169

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

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

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

    
1195
	return false;
1196
}
1197

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

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

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

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