Project

General

Profile

Download (37.2 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" => "1000",
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
	/* 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
	$failed = array();
285
	foreach ($gateways_arr as $gateway) {
286
		if (!isset($gateway['enable_dpinger'])) {
287
			continue;
288
		}
289

    
290
		if (start_dpinger($gateway) != 0) {
291
			/*
292
			 * Save process didn't start and try
293
			 * again later
294
			 */
295
			$failed[] = $gateway['name'];
296
		}
297
	}
298

    
299
	if (!empty($failed)) {
300
		/* 1 second is enough for IPv6 DAD to finish */
301
		sleep(1);
302
		foreach ($gateways_arr as $gateway) {
303
			if (!in_array($gateway['name'], $failed)) {
304
				continue;
305
			}
306
			if (start_dpinger($gateway) != 0) {
307
				log_error("Error starting gateway monitor " .
308
				    "for {$gateway['name']}");
309
			}
310
		}
311
	}
312

    
313
	return;
314
}
315

    
316
function get_dpinger_status($gwname) {
317
	global $g;
318

    
319
	$running_processes = running_dpinger_processes();
320

    
321
	if (!isset($running_processes[$gwname])) {
322
		log_error("dpinger: No dpinger session running for gateway {$gwname}");
323
		return false;
324
	}
325

    
326
	$proc = $running_processes[$gwname];
327
	unset($running_processes);
328

    
329
	if (!file_exists($proc['socket'])) {
330
		log_error("dpinger: status socket {$proc['socket']} not found");
331
		return false;
332
	}
333

    
334
	$fp = stream_socket_client("unix://{$proc['socket']}", $errno, $errstr, 10);
335
	if (!$fp) {
336
		log_error("dpinger: cannot connect to status socket {$proc['socket']} - $errstr ($errno)");
337
		return false;
338
	}
339

    
340
	$status = '';
341
	while (!feof($fp)) {
342
		$status .= fgets($fp, 1024);
343
	}
344
	fclose($fp);
345

    
346
	$r = array();
347
	list(
348
	    $r['gwname'],
349
	    $r['latency_avg'],
350
	    $r['latency_stddev'],
351
	    $r['loss']
352
	) = explode(' ', preg_replace('/\n/', '', $status));
353

    
354
	$r['srcip'] = $proc['srcip'];
355
	$r['targetip'] = $proc['targetip'];
356

    
357
	$gateways_arr = return_gateways_array();
358
	unset($gw);
359
	if (isset($gateways_arr[$gwname])) {
360
		$gw = $gateways_arr[$gwname];
361
	}
362

    
363
	$r['latency_avg'] = round($r['latency_avg']/1000, 3);
364
	$r['latency_stddev'] = round($r['latency_stddev']/1000, 3);
365

    
366
	$r['status'] = "none";
367
	if (isset($gw) && isset($gw['force_down'])) {
368
		$r['status'] = "force_down";
369
	} else if (isset($gw)) {
370
		$settings = return_dpinger_defaults();
371

    
372
		$keys = array(
373
		    'latencylow',
374
		    'latencyhigh',
375
		    'losslow',
376
		    'losshigh'
377
		);
378

    
379
		/* Replace default values by user-defined */
380
		foreach ($keys as $key) {
381
			if (isset($gw[$key]) && is_numeric($gw[$key])) {
382
				$settings[$key] = $gw[$key];
383
			}
384
		}
385

    
386
		if ($r['latency_avg'] > $settings['latencyhigh'] ||
387
		    $r['loss'] > $settings['losshigh']) {
388
			$r['status'] = "down";
389
		} else if ($r['latency_avg'] > $settings['latencylow']) {
390
			$r['status'] = "delay";
391
		} else if ($r['loss'] > $settings['losslow']) {
392
			$r['status'] = "loss";
393
		}
394
	}
395

    
396
	return $r;
397
}
398

    
399
/* return the status of the dpinger targets as an array */
400
function return_gateways_status($byname = false) {
401
	global $config, $g;
402

    
403
	$dpinger_gws = running_dpinger_processes();
404
	$status = array();
405

    
406
	$gateways_arr = return_gateways_array();
407

    
408
	foreach ($dpinger_gws as $gwname => $gwdata) {
409
		$dpinger_status = get_dpinger_status($gwname);
410
		if ($dpinger_status === false) {
411
			continue;
412
		}
413

    
414
		if ($byname == false) {
415
			$target = $dpinger_status['targetip'];
416
		} else {
417
			$target = $gwname;
418
		}
419

    
420
		$status[$target] = array();
421
		$status[$target]['monitorip'] = $dpinger_status['targetip'];
422
		$status[$target]['srcip'] = $dpinger_status['srcip'];
423
		$status[$target]['name'] = $gwname;
424
		$status[$target]['delay'] = empty($dpinger_status['latency_avg']) ? "0ms" : $dpinger_status['latency_avg'] . "ms";
425
		$status[$target]['loss'] = empty($dpinger_status['loss']) ? "0.0%" : round($dpinger_status['loss'], 1) . "%";
426
		$status[$target]['status'] = $dpinger_status['status'];
427
	}
428

    
429
	/* tack on any gateways that have monitoring disabled
430
	 * or are down, which could cause gateway groups to fail */
431
	$gateways_arr = return_gateways_array();
432
	foreach ($gateways_arr as $gwitem) {
433
		if (!isset($gwitem['monitor_disable'])) {
434
			continue;
435
		}
436
		if (!is_ipaddr($gwitem['monitor'])) {
437
			$realif = $gwitem['interface'];
438
			$tgtip = get_interface_gateway($realif);
439
			if (!is_ipaddr($tgtip)) {
440
				$tgtip = "none";
441
			}
442
			$srcip = find_interface_ip($realif);
443
		} else {
444
			$tgtip = $gwitem['monitor'];
445
			$srcip = find_interface_ip($realif);
446
		}
447
		if ($byname == true) {
448
			$target = $gwitem['name'];
449
		} else {
450
			$target = $tgtip;
451
		}
452

    
453
		/* failsafe for down interfaces */
454
		if ($target == "none") {
455
			$target = $gwitem['name'];
456
			$status[$target]['name'] = $gwitem['name'];
457
			$status[$target]['delay'] = "0.0ms";
458
			$status[$target]['loss'] = "100.0%";
459
			$status[$target]['status'] = "down";
460
		} else {
461
			$status[$target]['monitorip'] = $tgtip;
462
			$status[$target]['srcip'] = $srcip;
463
			$status[$target]['name'] = $gwitem['name'];
464
			$status[$target]['delay'] = "0.0ms";
465
			$status[$target]['loss'] = "0.0%";
466
			$status[$target]['status'] = "none";
467
		}
468
	}
469
	return($status);
470
}
471

    
472
/* Return all configured gateways on the system */
473
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
474
	global $config, $g;
475

    
476
	$gateways_arr = array();
477
	$gateways_arr_temp = array();
478

    
479
	$found_defaultv4 = 0;
480
	$found_defaultv6 = 0;
481

    
482
	// Ensure the interface cache is up to date first
483
	$interfaces = get_interface_arr(true);
484
	$interfaces_v4 = array();
485
	$interfaces_v6 = array();
486

    
487
	$i = -1;
488
	/* Process/add all the configured gateways. */
489
	if (is_array($config['gateways']['gateway_item'])) {
490
		foreach ($config['gateways']['gateway_item'] as $gateway) {
491
			/* Increment it here to do not skip items */
492
			$i++;
493

    
494
			if (empty($config['interfaces'][$gateway['interface']])) {
495
				if ($inactive === false) {
496
					continue;
497
				} else {
498
					$gateway['inactive'] = true;
499
				}
500
			}
501
			$wancfg = $config['interfaces'][$gateway['interface']];
502

    
503
			/* skip disabled interfaces */
504
			if ($disabled === false && (!isset($wancfg['enable']))) {
505
				continue;
506
			}
507

    
508
			/* if the gateway is dynamic and we can find the IPv4, Great! */
509
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
510
				if ($gateway['ipprotocol'] == "inet") {
511
					/* we know which interfaces is dynamic, this should be made a function */
512
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
513
					/* no IP address found, set to dynamic */
514
					if (!is_ipaddrv4($gateway['gateway'])) {
515
						$gateway['gateway'] = "dynamic";
516
					}
517
					$gateway['dynamic'] = true;
518
				}
519

    
520
				/* if the gateway is dynamic and we can find the IPv6, Great! */
521
				else if ($gateway['ipprotocol'] == "inet6") {
522
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
523
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
524
					/* no IPv6 address found, set to dynamic */
525
					if (!is_ipaddrv6($gateway['gateway'])) {
526
						$gateway['gateway'] = "dynamic";
527
					}
528
					$gateway['dynamic'] = true;
529
				}
530
			} else {
531
				/* getting this detection right is hard at this point because we still don't
532
				 * store the address family in the gateway item */
533
				if (is_ipaddrv4($gateway['gateway'])) {
534
					$gateway['ipprotocol'] = "inet";
535
				} else if (is_ipaddrv6($gateway['gateway'])) {
536
					$gateway['ipprotocol'] = "inet6";
537
				}
538
			}
539

    
540
			if (isset($gateway['monitor_disable'])) {
541
				$gateway['monitor_disable'] = true;
542
			} else if (empty($gateway['monitor'])) {
543
				$gateway['monitor'] = $gateway['gateway'];
544
			}
545

    
546
			$gateway['friendlyiface'] = $gateway['interface'];
547

    
548
			/* special treatment for tunnel interfaces */
549
			if ($gateway['ipprotocol'] == "inet6") {
550
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
551
				$interfaces_v6[$gateway['friendlyiface']] = $gateway['friendlyiface'];
552
			} else {
553
				$gateway['interface'] = get_real_interface($gateway['interface'], "all", false, false);
554
				$interfaces_v4[$gateway['friendlyiface']] = $gateway['friendlyiface'];
555
			}
556

    
557
			/* entry has a default flag, use it */
558
			if (isset($gateway['defaultgw'])) {
559
				if ($gateway['ipprotocol'] == "inet") {
560
					$gateway['defaultgw'] = true;
561
					$found_defaultv4 = 1;
562
				} else if ($gateway['ipprotocol'] == "inet6") {
563
					$gateway['defaultgw'] = true;
564
					$found_defaultv6 = 1;
565
				}
566
			}
567
			/* include the gateway index as the attribute */
568
			$gateway['attribute'] = $i;
569

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

    
574
			/* skip disabled gateways if the caller has not asked for them to be returned. */
575
			if (!($disabled === false && isset($gateway['disabled']))) {
576
				$gateways_arr[$gateway['name']] = $gateway;
577
			}
578
		}
579
	}
580
	unset($gateway);
581

    
582
	/* Loop through all interfaces with a gateway and add it to a array */
583
	if ($disabled == false) {
584
		$iflist = get_configured_interface_with_descr();
585
	} else {
586
		$iflist = get_configured_interface_with_descr(false, true);
587
	}
588

    
589
	/* Process/add dynamic v4 gateways. */
590
	foreach ($iflist as $ifname => $friendly) {
591
		if (!interface_has_gateway($ifname)) {
592
			continue;
593
		}
594

    
595
		if (empty($config['interfaces'][$ifname])) {
596
			continue;
597
		}
598

    
599
		$ifcfg = &$config['interfaces'][$ifname];
600
		if (!isset($ifcfg['enable'])) {
601
			continue;
602
		}
603

    
604
		if (!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr'])) {
605
			continue;
606
		}
607

    
608
		if (isset($interfaces_v4[$ifname])) {
609
			continue;
610
		}
611

    
612
		$ctype = "";
613
		switch ($ifcfg['ipaddr']) {
614
			case "dhcp":
615
			case "pppoe":
616
			case "pptp":
617
			case "ppp":
618
				$ctype = strtoupper($ifcfg['ipaddr']);
619
				break;
620
			default:
621
				$tunnelif = substr($ifcfg['if'], 0, 3);
622
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
623
					// if current iface is an ovpn server endpoint then check its type, skip tap only
624
					if (substr($ifcfg['if'], 4, 1) == 's') {
625
						$ovpnid = substr($ifcfg['if'], 5);
626
						if (is_array($config['openvpn']['openvpn-server'])) {
627
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
628
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
629
									if ($ovpnserverconf['dev_mode'] == "tap") {
630
										continue 3;
631
									}
632
								}
633
							}
634
						}
635
					}
636
					$ctype = "VPNv4";
637
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
638
					$ctype = "TUNNELv4";
639
				}
640
				break;
641
		}
642
		$ctype = "_". strtoupper($ctype);
643

    
644
		$gateway = array();
645
		$gateway['dynamic'] = false;
646
		$gateway['ipprotocol'] = "inet";
647
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
648
		$gateway['interface'] = get_real_interface($ifname);
649
		$gateway['friendlyiface'] = $ifname;
650
		$gateway['name'] = "{$friendly}{$ctype}";
651
		$gateway['attribute'] = "system";
652

    
653
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
654
			$gateway['defaultgw'] = true;
655
			$gateway['dynamic'] = true;
656
			$found_defaultv4 = 1;
657
		}
658
		/* Loopback dummy for dynamic interfaces without a IP */
659
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true) {
660
			$gateway['gateway'] = "dynamic";
661
		}
662

    
663
		/* automatically skip known static and dynamic gateways that were previously processed */
664
		foreach ($gateways_arr_temp as $gateway_item) {
665
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
666
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
667
				continue 2;
668
			}
669
		}
670

    
671
		if (is_ipaddrv4($gateway['gateway'])) {
672
			$gateway['monitor'] = $gateway['gateway'];
673
		}
674

    
675
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
676
		$gateways_arr[$gateway['name']] = $gateway;
677
	}
678
	unset($gateway);
679

    
680
	/* Process/add dynamic v6 gateways. */
681
	foreach ($iflist as $ifname => $friendly) {
682
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
683
		if (!isset($config['system']['ipv6allow'])) {
684
			break;
685
		}
686

    
687
		if (!interface_has_gatewayv6($ifname)) {
688
			continue;
689
		}
690

    
691
		if (empty($config['interfaces'][$ifname])) {
692
			continue;
693
		}
694

    
695
		$ifcfg = &$config['interfaces'][$ifname];
696
		if (!isset($ifcfg['enable'])) {
697
			continue;
698
		}
699

    
700
		if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
701
			continue;
702
		}
703

    
704
		if (isset($interfaces_v6[$ifname])) {
705
			continue;
706
		}
707

    
708
		$ctype = "";
709
		switch ($ifcfg['ipaddrv6']) {
710
			case "slaac":
711
			case "dhcp6":
712
			case "6to4":
713
			case "6rd":
714
				$ctype = strtoupper($ifcfg['ipaddrv6']);
715
				break;
716
			default:
717
				$tunnelif = substr($ifcfg['if'], 0, 3);
718
				if (substr($ifcfg['if'], 0, 4) == "ovpn") {
719
					// if current iface is an ovpn server endpoint then check its type, skip tap only
720
					if (substr($ifcfg['if'], 4, 1) == 's') {
721
						$ovpnid = substr($ifcfg['if'], 5);
722
						if (is_array($config['openvpn']['openvpn-server'])) {
723
							foreach ($config['openvpn']['openvpn-server'] as & $ovpnserverconf) {
724
								if ($ovpnserverconf['vpnid'] == $ovpnid) {
725
									if ($ovpnserverconf['dev_mode'] == "tap") {
726
										continue 3;
727
									}
728
								}
729
							}
730
						}
731
					}
732
					$ctype = "VPNv6";
733
				} else if ($tunnelif == "gif" || $tunnelif == "gre") {
734
					$ctype = "TUNNELv6";
735
				}
736
				break;
737
		}
738
		$ctype = "_". strtoupper($ctype);
739

    
740
		$gateway = array();
741
		$gateway['dynamic'] = false;
742
		$gateway['ipprotocol'] = "inet6";
743
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
744
		$gateway['interface'] = get_real_interface($ifname, "inet6");
745
		switch ($ifcfg['ipaddrv6']) {
746
			case "6rd":
747
			case "6to4":
748
				$gateway['dynamic'] = "default";
749
				break;
750
		}
751
		$gateway['friendlyiface'] = $ifname;
752
		$gateway['name'] = "{$friendly}{$ctype}";
753
		$gateway['attribute'] = "system";
754

    
755
		if (($gateway['dynamic'] === "default") && ($found_defaultv6 == 0)) {
756
			$gateway['defaultgw'] = true;
757
			$gateway['dynamic'] = true;
758
			$found_defaultv6 = 1;
759
		}
760

    
761
		/* Loopback dummy for dynamic interfaces without a IP */
762
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true) {
763
			$gateway['gateway'] = "dynamic";
764
		}
765

    
766
		/* automatically skip known static and dynamic gateways that were previously processed */
767
		foreach ($gateways_arr_temp as $gateway_item) {
768
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
769
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
770
				continue 2;
771
			}
772
		}
773

    
774
		if (is_ipaddrv6($gateway['gateway'])) {
775
			$gateway['monitor'] = $gateway['gateway'];
776
		}
777

    
778
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
779
		$gateways_arr[$gateway['name']] = $gateway;
780
	}
781
	unset($gateway);
782

    
783
	/* FIXME: Should this be enabled.
784
	 * Some interface like wan might be default but have no info recorded
785
	 * the config. */
786
	/* this is a fallback if all else fails and we want to get packets out @smos */
787
	if ($found_defaultv4 == 0 || $found_defaultv6 == 0) {
788
		foreach ($gateways_arr as &$gateway) {
789
			if (($gateway['friendlyiface'] == "wan") && ($found_defaultv4 == 0) && (!isset($gateway['ipprotocol']) || ($gateway['ipprotocol'] == "inet"))) {
790
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw")) {
791
					$gateway['defaultgw'] = true;
792
					$found_defaultv4 = 1;
793
				}
794
			}
795
			else if (($gateway['friendlyiface'] == "wan") && ($found_defaultv6 == 0) && ($gateway['ipprotocol'] == "inet6")) {
796
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgwv6")) {
797
					$gateway['defaultgw'] = true;
798
					$found_defaultv6 = 1;
799
				}
800
			}
801
		}
802
	}
803

    
804
	if ($localhost === true) {
805
		/* attach localhost for Null routes */
806
		$gwlo4 = array();
807
		$gwlo4['name'] = "Null4";
808
		$gwlo4['interface'] = "lo0";
809
		$gwlo4['ipprotocol'] = "inet";
810
		$gwlo4['gateway'] = "127.0.0.1";
811
		$gwlo6 = array();
812
		$gwlo6['name'] = "Null6";
813
		$gwlo6['interface'] = "lo0";
814
		$gwlo6['ipprotocol'] = "inet6";
815
		$gwlo6['gateway'] = "::1";
816
		$gateways_arr['Null4'] = $gwlo4;
817
		$gateways_arr['Null6'] = $gwlo6;
818
	}
819
	return($gateways_arr);
820
}
821

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

    
882
/*
883
 * Return an array with all gateway groups with name as key
884
 * All gateway groups will be processed before returning the array.
885
 */
886
function return_gateway_groups_array() {
887
	global $config, $g;
888

    
889
	/* fetch the current gateways status */
890
	$gateways_status = return_gateways_status(true);
891
	$gateways_arr = return_gateways_array();
892
	$gateway_groups_array = array();
893

    
894
	if (isset($config['system']['gw_switch_default'])) {
895
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
896
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
897
	}
898
	if (is_array($config['gateways']['gateway_group'])) {
899
		$carplist = get_configured_carp_interface_list();
900
		foreach ($config['gateways']['gateway_group'] as $group) {
901
			/* create array with group gateways members separated by tier */
902
			$tiers = array();
903
			$backupplan = array();
904
			$gwvip_arr = array();
905
			foreach ($group['item'] as $item) {
906
				list($gwname, $tier, $vipname) = explode("|", $item);
907

    
908
				if (is_ipaddr($carplist[$vipname])) {
909
					if (!is_array($gwvip_arr[$group['name']])) {
910
						$gwvip_arr[$group['name']] = array();
911
					}
912
					$gwvip_arr[$group['name']][$gwname] = $vipname;
913
				}
914

    
915
				/* Do it here rather than reiterating again the group in case no member is up. */
916
				if (!is_array($backupplan[$tier])) {
917
					$backupplan[$tier] = array();
918
				}
919
				$backupplan[$tier][] = $gwname;
920

    
921
				/* check if the gateway is available before adding it to the array */
922
				if (is_array($gateways_status[$gwname])) {
923
					$status = $gateways_status[$gwname];
924
					$gwdown = false;
925
					if (stristr($status['status'], "down")) {
926
						$msg = sprintf(gettext("MONITOR: %s is down, omitting from routing group {$group['name']}"), $gwname);
927
						$gwdown = true;
928
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
929
						/* packet loss */
930
						$msg = sprintf(gettext("MONITOR: %s has packet loss, omitting from routing group {$group['name']}"), $gwname);
931
						$gwdown = true;
932
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
933
						/* high latency */
934
						$msg = sprintf(gettext("MONITOR: %s has high latency, omitting from routing group {$group['name']}"), $gwname);
935
						$gwdown = true;
936
					}
937
					if ($gwdown == true) {
938
						log_error($msg);
939
						notify_via_growl($msg);
940
						notify_via_smtp($msg);
941
					} else {
942
						/* Online add member */
943
						if (!is_array($tiers[$tier])) {
944
							$tiers[$tier] = array();
945
						}
946
						$tiers[$tier][] = $gwname;
947
					}
948
				} else if (isset($gateways_arr[$gwname]['monitor_disable'])) {
949
					$tiers[$tier][] = $gwname;
950
				}
951
			}
952
			$tiers_count = count($tiers);
953
			if ($tiers_count == 0) {
954
				/* Oh dear, we have no members! Engage Plan B */
955
				if (!platform_booting()) {
956
					$msg = gettext("Gateways status could not be determined, considering all as up/active. (Group: {$group['name']})");
957
					log_error($msg);
958
					notify_via_growl($msg);
959
					//notify_via_smtp($msg);
960
				}
961
				$tiers = $backupplan;
962
			}
963
			/* sort the tiers array by the tier key */
964
			ksort($tiers);
965

    
966
			/* we do not really foreach the tiers as we stop after the first tier */
967
			foreach ($tiers as $tieridx => $tier) {
968
				/* process all gateways in this tier */
969
				foreach ($tier as $member) {
970
					/* determine interface gateway */
971
					if (isset($gateways_arr[$member])) {
972
						$gateway = $gateways_arr[$member];
973
						$int = $gateway['interface'];
974
						$gatewayip = "";
975
						if (is_ipaddr($gateway['gateway'])) {
976
							$gatewayip = $gateway['gateway'];
977
						} else if (!empty($int)) {
978
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
979
						}
980

    
981
						if (!empty($int)) {
982
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
983
							if (is_ipaddr($gatewayip)) {
984
								$groupmember = array();
985
								$groupmember['int'] = $int;
986
								$groupmember['gwip'] = $gatewayip;
987
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
988
								if (is_array($gwvip_arr[$group['name']])&& !empty($gwvip_arr[$group['name']][$member])) {
989
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
990
								}
991
								$gateway_groups_array[$group['name']][] = $groupmember;
992
							}
993
						}
994
					}
995
				}
996
				/* we should have the 1st available tier now, exit stage left */
997
				if (count($gateway_groups_array[$group['name']]) > 0) {
998
					break;
999
				} else {
1000
					log_error("GATEWAYS: Group {$group['name']} did not have any gateways up on tier {$tieridx}!");
1001
				}
1002
			}
1003
		}
1004
	}
1005

    
1006
	return ($gateway_groups_array);
1007
}
1008

    
1009
/* Update DHCP WAN Interface ip address in gateway group item */
1010
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
1011
	global $config, $g;
1012
	foreach ($config['gateways']['gateway_item'] as & $gw) {
1013
		if ($gw['interface'] == $interface) {
1014
			$current_gw = get_interface_gateway($interface);
1015
			if ($gw['gateway'] <> $current_gw) {
1016
				$gw['gateway'] = $current_gw;
1017
				$changed = true;
1018
			}
1019
		}
1020
	}
1021
	if ($changed && $current_gw) {
1022
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
1023
	}
1024
}
1025

    
1026
function lookup_gateway_ip_by_name($name, $disabled = false) {
1027

    
1028
	$gateways_arr = return_gateways_array($disabled, true);
1029
	foreach ($gateways_arr as $gname => $gw) {
1030
		if ($gw['name'] === $name || $gname === $name) {
1031
			return $gw['gateway'];
1032
		}
1033
	}
1034

    
1035
	return false;
1036
}
1037

    
1038
function lookup_gateway_monitor_ip_by_name($name) {
1039

    
1040
	$gateways_arr = return_gateways_array(false, true);
1041
	if (!empty($gateways_arr[$name])) {
1042
		$gateway = $gateways_arr[$name];
1043
		if (!is_ipaddr($gateway['monitor'])) {
1044
			return $gateway['gateway'];
1045
		}
1046

    
1047
		return $gateway['monitor'];
1048
	}
1049

    
1050
	return (false);
1051
}
1052

    
1053
function lookup_gateway_interface_by_name($name) {
1054

    
1055
	$gateways_arr = return_gateways_array(false, true);
1056
	if (!empty($gateways_arr[$name])) {
1057
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
1058
		return ($interfacegw);
1059
	}
1060

    
1061
	return (false);
1062
}
1063

    
1064
function get_interface_gateway($interface, &$dynamic = false) {
1065
	global $config, $g;
1066

    
1067
	if (substr($interface, 0, 4) == '_vip') {
1068
		$interface = get_configured_carp_interface_list($interface, 'inet', 'iface');
1069
	}
1070

    
1071
	$gw = NULL;
1072
	$gwcfg = $config['interfaces'][$interface];
1073
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
1074
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1075
			if (($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
1076
				$gw = $gateway['gateway'];
1077
				break;
1078
			}
1079
		}
1080
	}
1081

    
1082
	// for dynamic interfaces we handle them through the $interface_router file.
1083
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
1084
		$realif = get_real_interface($interface);
1085
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
1086
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
1087
			$dynamic = true;
1088
		}
1089
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw")) {
1090
			$dynamic = "default";
1091
		}
1092

    
1093
	}
1094

    
1095
	/* return gateway */
1096
	return ($gw);
1097
}
1098

    
1099
function get_interface_gateway_v6($interface, &$dynamic = false) {
1100
	global $config, $g;
1101

    
1102
	if (substr($interface, 0, 4) == '_vip') {
1103
		$interface = get_configured_carp_interface_list($interface, 'inet6', 'iface');
1104
	}
1105

    
1106
	$gw = NULL;
1107
	$gwcfg = $config['interfaces'][$interface];
1108
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1109
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1110
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1111
				$gw = $gateway['gateway'];
1112
				break;
1113
			}
1114
		}
1115
	}
1116

    
1117
	// for dynamic interfaces we handle them through the $interface_router file.
1118
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1119
		$realif = get_real_interface($interface);
1120
		if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1121
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1122
			$dynamic = true;
1123
		}
1124
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6")) {
1125
			$dynamic = "default";
1126
		}
1127
	}
1128
	/* return gateway */
1129
	return ($gw);
1130
}
1131

    
1132
/* Check a IP address against a gateway IP or name
1133
 * to verify it's address family */
1134
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1135
	$v4ip = false;
1136
	$v6ip = false;
1137
	$v4gw = false;
1138
	$v6gw = false;
1139

    
1140
	if (is_ipaddrv4($ipaddr)) {
1141
		$v4ip = true;
1142
	}
1143
	if (is_ipaddrv6($ipaddr)) {
1144
		$v6ip = true;
1145
	}
1146
	if (is_ipaddrv4($gwname)) {
1147
		$v4gw = true;
1148
	}
1149
	if (is_ipaddrv6($gwname)) {
1150
		$v6gw = true;
1151
	}
1152

    
1153
	if ($v4ip && $v4gw) {
1154
		return true;
1155
	}
1156
	if ($v6ip && $v6gw) {
1157
		return true;
1158
	}
1159

    
1160
	/* still no match, carry on, lookup gateways */
1161
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1162
		$v4gw = true;
1163
	}
1164
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1165
		$v6gw = true;
1166
	}
1167

    
1168
	$gw_array = return_gateways_array();
1169
	if (is_array($gw_array[$gwname])) {
1170
		switch ($gw_array[$gwname]['ipprotocol']) {
1171
			case "inet":
1172
				$v4gw = true;
1173
				break;
1174
			case "inet6":
1175
				$v6gw = true;
1176
				break;
1177
		}
1178
	}
1179

    
1180
	if ($v4ip && $v4gw) {
1181
		return true;
1182
	}
1183
	if ($v6ip && $v6gw) {
1184
		return true;
1185
	}
1186

    
1187
	return false;
1188
}
1189

    
1190
/* check if a interface is part of a gateway group */
1191
function interface_gateway_group_member($interface) {
1192
	global $config;
1193

    
1194
	if (is_array($config['gateways']['gateway_group'])) {
1195
		$groups = $config['gateways']['gateway_group'];
1196
	} else {
1197
		return false;
1198
	}
1199

    
1200
	$gateways_arr = return_gateways_array(false, true);
1201
	foreach ($groups as $group) {
1202
		if (is_array($group['item'])) {
1203
			foreach ($group['item'] as $item) {
1204
				$elements = explode("|", $item);
1205
				$gwname = $elements[0];
1206
				if ($interface == $gateways_arr[$gwname]['interface']) {
1207
					unset($gateways_arr);
1208
					return true;
1209
				}
1210
			}
1211
		}
1212
	}
1213
	unset($gateways_arr);
1214

    
1215
	return false;
1216
}
1217

    
1218
function gateway_is_gwgroup_member($name) {
1219
	global $config;
1220

    
1221
	if (is_array($config['gateways']['gateway_group'])) {
1222
		$groups = $config['gateways']['gateway_group'];
1223
	} else {
1224
		return false;
1225
	}
1226

    
1227
	$members = array();
1228
	foreach ($groups as $group) {
1229
		if (is_array($group['item'])) {
1230
			foreach ($group['item'] as $item) {
1231
				$elements = explode("|", $item);
1232
				$gwname = $elements[0];
1233
				if ($name == $elements[0]) {
1234
					$members[] = $group['name'];
1235
				}
1236
			}
1237
		}
1238
	}
1239

    
1240
	return $members;
1241
}
1242
?>
(24-24/65)