Project

General

Profile

Download (36.8 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" => "1250",
42
		"time_period" => "30000",
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
	/* Make sure we don't end up with 2 process for the same GW */
157
	stop_dpinger($gateway['name']);
158

    
159
	/* Redirect stdout to /dev/null to avoid exec() to wait for dpinger */
160
	return mwexec("/usr/local/bin/dpinger {$params} {$gateway['monitor']} >/dev/null");
161
}
162

    
163
/*
164
 * Starts dpinger processes and adds appropriate static routes for monitor IPs
165
 */
166
function setup_gateways_monitor() {
167
	global $config, $g;
168

    
169
	$gateways_arr = return_gateways_array();
170
	if (!is_array($gateways_arr)) {
171
		log_error("No gateways to monitor. dpinger will not run.");
172
		stop_dpinger();
173
		return;
174
	}
175

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

    
190
		/* if the monitor address is already used before, skip */
191
		if (in_array($gateway['monitor'], $monitor_ips)) {
192
			continue;
193
		}
194

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

    
208
			if ($gwifip == "0.0.0.0") {
209
				continue; //Skip this target - the gateway is still waiting for DHCP
210
			}
211

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

    
228
				pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp");
229
			}
230
		} else if ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway...
231
			if (is_linklocal($gateway['gateway']) &&
232
			    get_ll_scope($gateway['gateway']) == '') {
233
				$gateways_arr[$gwname]['gateway'] .= '%' . $gateway['interface'];
234
			}
235

    
236
			if (is_linklocal($gateway['monitor'])) {
237
				if (get_ll_scope($gateway['monitor']) == '') {
238
					$gateways_arr[$gwname]['monitor'] .= '%' . $gateway['interface'];
239
				}
240

    
241
				$gwifip = find_interface_ipv6_ll($gateway['interface'], true);
242

    
243
				if (get_ll_scope($gwifip) == '') {
244
					$gwifip .= '%' . $gateway['interface'];
245
				}
246
			} else {
247
				$gwifip = find_interface_ipv6($gateway['interface'], true);
248
			}
249

    
250
			if (!is_ipaddrv6($gwifip)) {
251
				continue; //Skip this target
252
			}
253

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

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

    
276
		$monitor_ips[] = $gateway['monitor'];
277
		$gateways_arr[$gwname]['enable_dpinger'] = true;
278
		$gateways_arr[$gwname]['gwifip'] = $gwifip;
279
	}
280

    
281
	stop_dpinger();
282

    
283
	/* Start new processes */
284
	foreach ($gateways_arr as $gateway) {
285
		if (!isset($gateway['enable_dpinger'])) {
286
			continue;
287
		}
288

    
289
		if (start_dpinger($gateway) != 0) {
290
			log_error("Error starting gateway monitor for " .
291
			    $gateway['name']);
292
		}
293
	}
294

    
295
	return;
296
}
297

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

    
301
	$running_processes = running_dpinger_processes();
302

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

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

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

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

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

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

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

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

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

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

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

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

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

    
378
	return $r;
379
}
380

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

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

    
388
	$gateways_arr = return_gateways_array();
389

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
988
	return ($gateway_groups_array);
989
}
990

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

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

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

    
1017
	return false;
1018
}
1019

    
1020
function lookup_gateway_monitor_ip_by_name($name) {
1021

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

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

    
1032
	return (false);
1033
}
1034

    
1035
function lookup_gateway_interface_by_name($name) {
1036

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

    
1043
	return (false);
1044
}
1045

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

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

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

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

    
1075
	}
1076

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

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

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

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

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

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

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

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

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

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

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

    
1169
	return false;
1170
}
1171

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

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

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

    
1197
	return false;
1198
}
1199

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

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

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

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