Project

General

Profile

Download (38 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	gwlb.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (C) 2008 Bill Marquette, Seth Mos
7
	Copyright (c) 2008-2016 Electric Sheep Fencing, LLC. All rights reserved.
8

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

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

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

    
20
	3. All advertising materials mentioning features or use of this software
21
	   must display the following acknowledgment:
22
	   "This product includes software developed by the pfSense Project
23
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
24

    
25
	4. The names "pfSense" and "pfSense Project" must not be used to
26
	   endorse or promote products derived from this software without
27
	   prior written permission. For written permission, please contact
28
	   coreteam@pfsense.org.
29

    
30
	5. Products derived from this software may not be called "pfSense"
31
	   nor may "pfSense" appear in their names without prior written
32
	   permission of the Electric Sheep Fencing, LLC.
33

    
34
	6. Redistributions of any form whatsoever must retain the following
35
	   acknowledgment:
36

    
37
	"This product includes software developed by the pfSense Project
38
	for use in the pfSense software distribution (http://www.pfsense.org/).
39

    
40
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
	OF THE POSSIBILITY OF SUCH DAMAGE.
52
 */
53

    
54
require_once("config.inc");
55
require_once("rrd.inc");
56

    
57
/* Returns an array of default values used for dpinger */
58
function return_dpinger_defaults() {
59
	return array(
60
		"latencylow" => "200",
61
		"latencyhigh" => "500",
62
		"losslow" => "10",
63
		"losshigh" => "20",
64
		"interval" => "250",
65
		"loss_interval" => "1250",
66
		"time_period" => "30000",
67
		"alert_interval" => "1000",
68
		"data_payload" => "0");
69
}
70

    
71
function running_dpinger_processes() {
72
	global $g;
73

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

    
76
	$result = array();
77
	if ($pidfiles === FALSE) {
78
		return $result;
79
	}
80

    
81
	foreach ($pidfiles as $pidfile) {
82
		if (preg_match('/^dpinger_(.+)_([^_]+)_([^_]+)\.pid$/',
83
		    basename($pidfile), $matches)) {
84
			$socket_file = preg_replace('/\.pid$/', '.sock',
85
			    $pidfile);
86
			$result[$matches[1]] = array(
87
			    'srcip'    => $matches[2],
88
			    'targetip' => $matches[3],
89
			    'pidfile'  => $pidfile,
90
			    'socket'   => $socket_file
91
			);
92
			unset($gwinfo);
93
		}
94
	}
95

    
96
	return $result;
97
}
98

    
99
/*
100
 * Stop one or more dpinger process
101
 * default parameter $gwname is '*' that will kill all running sessions
102
 * If a gateway name is passed, only this one will be killed
103
 */
104
function stop_dpinger($gwname = '') {
105
	global $g;
106

    
107
	$running_processes = running_dpinger_processes();
108

    
109
	foreach ($running_processes as $running_gwname => $process) {
110
		if ($gwname != '' && $running_gwname != $gwname) {
111
			continue;
112
		}
113

    
114
		if (isvalidpid($process['pidfile'])) {
115
			killbypid($process['pidfile']);
116
		} else {
117
			@unlink($process['pidfile']);
118
		}
119
	}
120
}
121

    
122
function start_dpinger($gateway) {
123
	global $g;
124

    
125
	if (!isset($gateway['gwifip'])) {
126
		return;
127
	}
128

    
129
	$dpinger_defaults = return_dpinger_defaults();
130

    
131
	$pidfile = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
132
	    "{$gateway['gwifip']}_{$gateway['monitor']}.pid";
133
	$socket = "{$g['varrun_path']}/dpinger_{$gateway['name']}_" .
134
	    "{$gateway['gwifip']}_{$gateway['monitor']}.sock";
135
	$alarm_cmd = "{$g['etc_path']}/rc.gateway_alarm";
136

    
137
	$params  = "-S ";			/* Log warnings via syslog */
138
	$params .= "-r 0 ";			/* Disable unused reporting thread */
139
	$params .= "-i {$gateway['name']} ";	/* Identifier */
140
	$params .= "-B {$gateway['gwifip']} ";	/* Bind src address */
141
	$params .= "-p {$pidfile} ";		/* PID filename */
142
	$params .= "-u {$socket} ";		/* Status Socket */
143
	$params .= "-C \"{$alarm_cmd}\" ";	/* Command to run on alarm */
144

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

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

    
157
	$params .= "-l " .
158
	    (isset($gateway['loss_interval']) && is_numeric($gateway['loss_interval'])
159
	    ?  $gateway['loss_interval']
160
	    : $dpinger_defaults['loss_interval']
161
	    ) . " ";
162

    
163
	$params .= "-t " .
164
	    (isset($gateway['time_period']) && is_numeric($gateway['time_period'])
165
	    ?  $gateway['time_period']
166
	    : $dpinger_defaults['time_period']
167
	    ) . " ";
168

    
169
	$params .= "-A " .
170
	    (isset($gateway['alert_interval']) && is_numeric($gateway['alert_interval'])
171
	    ?  $gateway['alert_interval']
172
	    : $dpinger_defaults['alert_interval']
173
	    ) . " ";
174

    
175
	$params .= "-D " .
176
	    (isset($gateway['latencyhigh']) && is_numeric($gateway['latencyhigh'])
177
	    ?  $gateway['latencyhigh']
178
	    : $dpinger_defaults['latencyhigh']
179
	    ) . " ";
180

    
181
	$params .= "-L " .
182
	    (isset($gateway['losshigh']) && is_numeric($gateway['losshigh'])
183
	    ?  $gateway['losshigh']
184
	    : $dpinger_defaults['losshigh']
185
	    ) . " ";
186

    
187
	/* Make sure we don't end up with 2 process for the same GW */
188
	stop_dpinger($gateway['name']);
189

    
190
	/* Redirect stdout to /dev/null to avoid exec() to wait for dpinger */
191
	return mwexec("/usr/local/bin/dpinger {$params} {$gateway['monitor']} >/dev/null");
192
}
193

    
194
/*
195
 * Starts dpinger processes and adds appropriate static routes for monitor IPs
196
 */
197
function setup_gateways_monitor() {
198
	global $config, $g;
199

    
200
	$gateways_arr = return_gateways_array();
201
	if (!is_array($gateways_arr)) {
202
		log_error("No gateways to monitor. dpinger will not run.");
203
		stop_dpinger();
204
		return;
205
	}
206

    
207
	$monitor_ips = array();
208
	foreach ($gateways_arr as $gwname => $gateway) {
209
		/* Do not monitor if such was requested */
210
		if (isset($gateway['monitor_disable'])) {
211
			continue;
212
		}
213
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
214
			if (is_ipaddr($gateway['gateway'])) {
215
				$gateways_arr[$gwname]['monitor'] = $gateway['gateway'];
216
			} else { /* No chance to get an ip to monitor skip target. */
217
				continue;
218
			}
219
		}
220

    
221
		/* if the monitor address is already used before, skip */
222
		if (in_array($gateway['monitor'], $monitor_ips)) {
223
			continue;
224
		}
225

    
226
		/* Interface ip is needed since dpinger will bind a socket to it.
227
		 * However the config GUI should already have checked this and when
228
		 * PPPoE is used the IP address is set to "dynamic". So using is_ipaddrv4
229
		 * or is_ipaddrv6 to identify packet type would be wrong, especially as
230
		 * further checks (that can cope with the "dynamic" case) are present inside
231
		 * the if block. So using $gateway['ipprotocol'] is the better option.
232
		 */
233
		if ($gateway['ipprotocol'] == "inet") { // This is an IPv4 gateway...
234
			$gwifip = find_interface_ip($gateway['interface'], true);
235
			if (!is_ipaddrv4($gwifip)) {
236
				continue; //Skip this target
237
			}
238

    
239
			if ($gwifip == "0.0.0.0") {
240
				continue; //Skip this target - the gateway is still waiting for DHCP
241
			}
242

    
243
			/*
244
			 * If the gateway is the same as the monitor we do not add a
245
			 * route as this will break the routing table.
246
			 * Add static routes for each gateway with their monitor IP
247
			 * not strictly necessary but is a added level of protection.
248
			 */
249
			if (is_ipaddrv4($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
250
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
251
				if (interface_isppp_type($gateway['friendlyiface'])) {
252
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
253
						" -iface " . escapeshellarg($gateway['interface']), true);
254
				} else {
255
					mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
256
						" " . escapeshellarg($gateway['gateway']), true);
257
				}
258

    
259
				pfSense_kill_states("0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmp");
260
			}
261
		} else if ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway...
262
			if (is_linklocal($gateway['gateway']) &&
263
			    get_ll_scope($gateway['gateway']) == '') {
264
				$gateways_arr[$gwname]['gateway'] .= '%' . $gateway['interface'];
265
			}
266

    
267
			if (is_linklocal($gateway['monitor'])) {
268
				if (get_ll_scope($gateway['monitor']) == '') {
269
					$gateways_arr[$gwname]['monitor'] .= '%' . $gateway['interface'];
270
				}
271

    
272
				$gwifip = find_interface_ipv6_ll($gateway['interface'], true);
273

    
274
				if (get_ll_scope($gwifip) == '') {
275
					$gwifip .= '%' . $gateway['interface'];
276
				}
277
			} else {
278
				$gwifip = find_interface_ipv6($gateway['interface'], true);
279
			}
280

    
281
			if (!is_ipaddrv6($gwifip)) {
282
				continue; //Skip this target
283
			}
284

    
285
			/*
286
			 * If the gateway is the same as the monitor we do not add a
287
			 * route as this will break the routing table.
288
			 * Add static routes for each gateway with their monitor IP
289
			 * not strictly necessary but is a added level of protection.
290
			 */
291
			if ($gateway['gateway'] != $gateway['monitor']) {
292
				log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
293
				if (interface_isppp_type($gateway['friendlyiface'])) {
294
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
295
						" -iface " . escapeshellarg($gateway['interface']), true);
296
				} else {
297
					mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gateway['monitor']) .
298
						" " . escapeshellarg($gateway['gateway']), true);
299
				}
300

    
301
				pfSense_kill_states("::0.0.0.0/0", $gateway['monitor'], $gateway['interface'], "icmpv6");
302
			}
303
		} else {
304
			continue;
305
		}
306

    
307
		$monitor_ips[] = $gateway['monitor'];
308
		$gateways_arr[$gwname]['enable_dpinger'] = true;
309
		$gateways_arr[$gwname]['gwifip'] = $gwifip;
310
	}
311

    
312
	stop_dpinger();
313

    
314
	/* Start new processes */
315
	foreach ($gateways_arr as $gateway) {
316
		if (!isset($gateway['enable_dpinger'])) {
317
			continue;
318
		}
319

    
320
		if (start_dpinger($gateway) != 0) {
321
			log_error("Error starting gateway monitor for " .
322
			    $gateway['name']);
323
		}
324
	}
325

    
326
	return;
327
}
328

    
329
function get_dpinger_status($gwname) {
330
	global $g;
331

    
332
	$running_processes = running_dpinger_processes();
333

    
334
	if (!isset($running_processes[$gwname])) {
335
		log_error("dpinger: No dpinger session running for gateway {$gwname}");
336
		return false;
337
	}
338

    
339
	$proc = $running_processes[$gwname];
340
	unset($running_processes);
341

    
342
	if (!file_exists($proc['socket'])) {
343
		log_error("dpinger: status socket {$proc['socket']} not found");
344
		return false;
345
	}
346

    
347
	$fp = stream_socket_client("unix://{$proc['socket']}", $errno, $errstr, 10);
348
	if (!$fp) {
349
		log_error("dpinger: cannot connect to status socket {$proc['socket']} - $errstr ($errno)");
350
		return false;
351
	}
352

    
353
	$status = '';
354
	while (!feof($fp)) {
355
		$status .= fgets($fp, 1024);
356
	}
357
	fclose($fp);
358

    
359
	$r = array();
360
	list(
361
	    $r['gwname'],
362
	    $r['latency_avg'],
363
	    $r['latency_stddev'],
364
	    $r['loss']
365
	) = explode(' ', preg_replace('/\n/', '', $status));
366

    
367
	$r['srcip'] = $proc['srcip'];
368
	$r['targetip'] = $proc['targetip'];
369

    
370
	$gateways_arr = return_gateways_array();
371
	unset($gw);
372
	if (isset($gateways_arr[$gwname])) {
373
		$gw = $gateways_arr[$gwname];
374
	}
375

    
376
	$r['latency_avg'] = round($r['latency_avg']/1000, 3);
377
	$r['latency_stddev'] = round($r['latency_stddev']/1000, 3);
378

    
379
	$r['status'] = "none";
380
	if (isset($gw) && isset($gw['force_down'])) {
381
		$r['status'] = "force_down";
382
	} else if (isset($gw)) {
383
		$settings = return_dpinger_defaults();
384

    
385
		$keys = array(
386
		    'latencylow',
387
		    'latencyhigh',
388
		    'losslow',
389
		    'losshigh'
390
		);
391

    
392
		/* Replace default values by user-defined */
393
		foreach ($keys as $key) {
394
			if (isset($gw[$key]) && is_numeric($gw[$key])) {
395
				$settings[$key] = $gw[$key];
396
			}
397
		}
398

    
399
		if ($r['latency_avg'] > $settings['latencyhigh'] ||
400
		    $r['loss'] > $settings['losshigh']) {
401
			$r['status'] = "down";
402
		} else if ($r['latency_avg'] > $settings['latencylow']) {
403
			$r['status'] = "delay";
404
		} else if ($r['loss'] > $settings['losslow']) {
405
			$r['status'] = "loss";
406
		}
407
	}
408

    
409
	return $r;
410
}
411

    
412
/* return the status of the dpinger targets as an array */
413
function return_gateways_status($byname = false) {
414
	global $config, $g;
415

    
416
	$dpinger_gws = running_dpinger_processes();
417
	$status = array();
418

    
419
	$gateways_arr = return_gateways_array();
420

    
421
	foreach ($dpinger_gws as $gwname => $gwdata) {
422
		$dpinger_status = get_dpinger_status($gwname);
423
		if ($dpinger_status === false) {
424
			continue;
425
		}
426

    
427
		if ($byname == false) {
428
			$target = $dpinger_status['targetip'];
429
		} else {
430
			$target = $gwname;
431
		}
432

    
433
		$status[$target] = array();
434
		$status[$target]['monitorip'] = $dpinger_status['targetip'];
435
		$status[$target]['srcip'] = $dpinger_status['srcip'];
436
		$status[$target]['name'] = $gwname;
437
		$status[$target]['delay'] = empty($dpinger_status['latency_avg']) ? "0ms" : $dpinger_status['latency_avg'] . "ms";
438
		$status[$target]['stddev'] = empty($dpinger_status['latency_stddev']) ? "0ms" : $dpinger_status['latency_stddev'] . "ms";
439
		$status[$target]['loss'] = empty($dpinger_status['loss']) ? "0.0%" : round($dpinger_status['loss'], 1) . "%";
440
		$status[$target]['status'] = $dpinger_status['status'];
441
	}
442

    
443
	/* tack on any gateways that have monitoring disabled
444
	 * or are down, which could cause gateway groups to fail */
445
	$gateways_arr = return_gateways_array();
446
	foreach ($gateways_arr as $gwitem) {
447
		if (!isset($gwitem['monitor_disable'])) {
448
			continue;
449
		}
450
		if (!is_ipaddr($gwitem['monitor'])) {
451
			$realif = $gwitem['interface'];
452
			$tgtip = get_interface_gateway($realif);
453
			if (!is_ipaddr($tgtip)) {
454
				$tgtip = "none";
455
			}
456
			$srcip = find_interface_ip($realif);
457
		} else {
458
			$tgtip = $gwitem['monitor'];
459
			$srcip = find_interface_ip($realif);
460
		}
461
		if ($byname == true) {
462
			$target = $gwitem['name'];
463
		} else {
464
			$target = $tgtip;
465
		}
466

    
467
		/* failsafe for down interfaces */
468
		if ($target == "none") {
469
			$target = $gwitem['name'];
470
			$status[$target]['name'] = $gwitem['name'];
471
			$status[$target]['delay'] = "0.0ms";
472
			$status[$target]['loss'] = "100.0%";
473
			$status[$target]['status'] = "down";
474
		} else {
475
			$status[$target]['monitorip'] = $tgtip;
476
			$status[$target]['srcip'] = $srcip;
477
			$status[$target]['name'] = $gwitem['name'];
478
			$status[$target]['delay'] = "";
479
			$status[$target]['loss'] = "";
480
			$status[$target]['status'] = "none";
481
		}
482
	}
483
	return($status);
484
}
485

    
486
/* Return all configured gateways on the system */
487
function return_gateways_array($disabled = false, $localhost = false, $inactive = false) {
488
	global $config, $g;
489

    
490
	$gateways_arr = array();
491
	$gateways_arr_temp = array();
492

    
493
	$found_defaultv4 = 0;
494
	$found_defaultv6 = 0;
495

    
496
	// Ensure the interface cache is up to date first
497
	$interfaces = get_interface_arr(true);
498

    
499
	$i = -1;
500
	/* Process/add all the configured gateways. */
501
	if (is_array($config['gateways']['gateway_item'])) {
502
		foreach ($config['gateways']['gateway_item'] as $gateway) {
503
			/* Increment it here to do not skip items */
504
			$i++;
505

    
506
			if (empty($config['interfaces'][$gateway['interface']])) {
507
				if ($inactive === false) {
508
					continue;
509
				} else {
510
					$gateway['inactive'] = true;
511
				}
512
			}
513
			$wancfg = $config['interfaces'][$gateway['interface']];
514

    
515
			/* skip disabled interfaces */
516
			if ($disabled === false && (!isset($wancfg['enable']))) {
517
				continue;
518
			}
519

    
520
			/* if the gateway is dynamic and we can find the IPv4, Great! */
521
			if (empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
522
				if ($gateway['ipprotocol'] == "inet") {
523
					/* we know which interfaces is dynamic, this should be made a function */
524
					$gateway['gateway'] = get_interface_gateway($gateway['interface']);
525
					/* no IP address found, set to dynamic */
526
					if (!is_ipaddrv4($gateway['gateway'])) {
527
						$gateway['gateway'] = "dynamic";
528
					}
529
					$gateway['dynamic'] = true;
530
				}
531

    
532
				/* if the gateway is dynamic and we can find the IPv6, Great! */
533
				else if ($gateway['ipprotocol'] == "inet6") {
534
					/* we know which interfaces is dynamic, this should be made a function, and for v6 too */
535
					$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
536
					/* no IPv6 address found, set to dynamic */
537
					if (!is_ipaddrv6($gateway['gateway'])) {
538
						$gateway['gateway'] = "dynamic";
539
					}
540
					$gateway['dynamic'] = true;
541
				}
542
			} else {
543
				/* getting this detection right is hard at this point because we still don't
544
				 * store the address family in the gateway item */
545
				if (is_ipaddrv4($gateway['gateway'])) {
546
					$gateway['ipprotocol'] = "inet";
547
				} else if (is_ipaddrv6($gateway['gateway'])) {
548
					$gateway['ipprotocol'] = "inet6";
549
				}
550
			}
551

    
552
			if (isset($gateway['monitor_disable'])) {
553
				$gateway['monitor_disable'] = true;
554
			} else if (empty($gateway['monitor'])) {
555
				$gateway['monitor'] = $gateway['gateway'];
556
			}
557

    
558
			$gateway['friendlyiface'] = $gateway['interface'];
559

    
560
			/* special treatment for tunnel interfaces */
561
			if ($gateway['ipprotocol'] == "inet6") {
562
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet6", false, false);
563
			} else {
564
				$gateway['interface'] = get_real_interface($gateway['interface'], "inet", false, false);
565
			}
566

    
567
			/* entry has a default flag, use it */
568
			if (isset($gateway['defaultgw'])) {
569
				if ($gateway['ipprotocol'] == "inet") {
570
					$gateway['defaultgw'] = true;
571
					$found_defaultv4 = 1;
572
				} else if ($gateway['ipprotocol'] == "inet6") {
573
					$gateway['defaultgw'] = true;
574
					$found_defaultv6 = 1;
575
				}
576
			}
577
			/* include the gateway index as the attribute */
578
			$gateway['attribute'] = $i;
579

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

    
584
			/* skip disabled gateways if the caller has not asked for them to be returned. */
585
			if (!($disabled === false && isset($gateway['disabled']))) {
586
				$gateways_arr[$gateway['name']] = $gateway;
587
			}
588
		}
589
	}
590
	unset($gateway);
591

    
592
	/* Loop through all interfaces with a gateway and add it to a array */
593
	if ($disabled == false) {
594
		$iflist = get_configured_interface_with_descr();
595
	} else {
596
		$iflist = get_configured_interface_with_descr(false, true);
597
	}
598

    
599
	/* Process/add dynamic v4 gateways. */
600
	foreach ($iflist as $ifname => $friendly) {
601
		if (!interface_has_gateway($ifname)) {
602
			continue;
603
		}
604

    
605
		if (empty($config['interfaces'][$ifname])) {
606
			continue;
607
		}
608

    
609
		$ifcfg = &$config['interfaces'][$ifname];
610
		if (!isset($ifcfg['enable'])) {
611
			continue;
612
		}
613

    
614
		if (!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr'])) {
615
			continue;
616
		}
617

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

    
650
		$gateway = array();
651
		$gateway['dynamic'] = false;
652
		$gateway['ipprotocol'] = "inet";
653
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
654
		$gateway['interface'] = get_real_interface($ifname);
655
		$gateway['friendlyiface'] = $ifname;
656
		$gateway['name'] = "{$friendly}{$ctype}";
657
		$gateway['attribute'] = "system";
658

    
659
		if (($gateway['dynamic'] === "default") && ($found_defaultv4 == 0)) {
660
			$gateway['defaultgw'] = true;
661
			$gateway['dynamic'] = true;
662
			$found_defaultv4 = 1;
663
		}
664
		/* Loopback dummy for dynamic interfaces without a IP */
665
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true) {
666
			$gateway['gateway'] = "dynamic";
667
		}
668

    
669
		/* automatically skip known static and dynamic gateways that were previously processed */
670
		foreach ($gateways_arr_temp as $gateway_item) {
671
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
672
			    (($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))) {
673
				continue 2;
674
			}
675
		}
676

    
677
		if (is_ipaddrv4($gateway['gateway'])) {
678
			$gateway['monitor'] = $gateway['gateway'];
679
		}
680

    
681
		$gateway['descr'] = "Interface {$friendly}{$ctype} Gateway";
682
		$gateways_arr[$gateway['name']] = $gateway;
683
	}
684
	unset($gateway);
685

    
686
	/* Process/add dynamic v6 gateways. */
687
	foreach ($iflist as $ifname => $friendly) {
688
		/* If the user has disabled IPv6, they probably don't want any IPv6 gateways. */
689
		if (!isset($config['system']['ipv6allow'])) {
690
			break;
691
		}
692

    
693
		if (!interface_has_gatewayv6($ifname)) {
694
			continue;
695
		}
696

    
697
		if (empty($config['interfaces'][$ifname])) {
698
			continue;
699
		}
700

    
701
		$ifcfg = &$config['interfaces'][$ifname];
702
		if (!isset($ifcfg['enable'])) {
703
			continue;
704
		}
705

    
706
		if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
707
			continue;
708
		}
709

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1007
	return ($gateway_groups_array);
1008
}
1009

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

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

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

    
1036
	return false;
1037
}
1038

    
1039
function lookup_gateway_monitor_ip_by_name($name) {
1040

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

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

    
1051
	return (false);
1052
}
1053

    
1054
function lookup_gateway_interface_by_name($name) {
1055

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

    
1062
	return (false);
1063
}
1064

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

    
1068
	if (substr($interface, 0, 4) == '_vip') {
1069
		$interface = get_configured_vip_interface($interface);
1070
		if (substr($interface, 0, 4) == '_vip') {
1071
			$interface = get_configured_vip_interface($interface);
1072
		}
1073
	}
1074

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

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

    
1097
	}
1098

    
1099
	/* return gateway */
1100
	return ($gw);
1101
}
1102

    
1103
function get_interface_gateway_v6($interface, &$dynamic = false) {
1104
	global $config, $g;
1105

    
1106
	if (substr($interface, 0, 4) == '_vip') {
1107
		$interface = get_configured_vip_interface($interface);
1108
		if (substr($interface, 0, 4) == '_vip') {
1109
			$interface = get_configured_vip_interface($interface);
1110
		}
1111
	}
1112

    
1113
	$gw = NULL;
1114
	$gwcfg = $config['interfaces'][$interface];
1115
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1116
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1117
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1118
				$gw = $gateway['gateway'];
1119
				break;
1120
			}
1121
		}
1122
	}
1123

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

    
1139
/* Check a IP address against a gateway IP or name
1140
 * to verify it's address family */
1141
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1142
	$v4ip = false;
1143
	$v6ip = false;
1144
	$v4gw = false;
1145
	$v6gw = false;
1146

    
1147
	if (is_ipaddrv4($ipaddr)) {
1148
		$v4ip = true;
1149
	}
1150
	if (is_ipaddrv6($ipaddr)) {
1151
		$v6ip = true;
1152
	}
1153
	if (is_ipaddrv4($gwname)) {
1154
		$v4gw = true;
1155
	}
1156
	if (is_ipaddrv6($gwname)) {
1157
		$v6gw = true;
1158
	}
1159

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

    
1167
	/* still no match, carry on, lookup gateways */
1168
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1169
		$v4gw = true;
1170
	}
1171
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1172
		$v6gw = true;
1173
	}
1174

    
1175
	$gw_array = return_gateways_array();
1176
	if (is_array($gw_array[$gwname])) {
1177
		switch ($gw_array[$gwname]['ipprotocol']) {
1178
			case "inet":
1179
				$v4gw = true;
1180
				break;
1181
			case "inet6":
1182
				$v6gw = true;
1183
				break;
1184
		}
1185
	}
1186

    
1187
	if ($v4ip && $v4gw) {
1188
		return true;
1189
	}
1190
	if ($v6ip && $v6gw) {
1191
		return true;
1192
	}
1193

    
1194
	return false;
1195
}
1196

    
1197
/* check if a interface is part of a gateway group */
1198
function interface_gateway_group_member($interface) {
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
	$gateways_arr = return_gateways_array(false, true);
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 ($interface == $gateways_arr[$gwname]['interface']) {
1214
					unset($gateways_arr);
1215
					return true;
1216
				}
1217
			}
1218
		}
1219
	}
1220
	unset($gateways_arr);
1221

    
1222
	return false;
1223
}
1224

    
1225
function gateway_is_gwgroup_member($name) {
1226
	global $config;
1227

    
1228
	if (is_array($config['gateways']['gateway_group'])) {
1229
		$groups = $config['gateways']['gateway_group'];
1230
	} else {
1231
		return false;
1232
	}
1233

    
1234
	$members = array();
1235
	foreach ($groups as $group) {
1236
		if (is_array($group['item'])) {
1237
			foreach ($group['item'] as $item) {
1238
				$elements = explode("|", $item);
1239
				$gwname = $elements[0];
1240
				if ($name == $elements[0]) {
1241
					$members[] = $group['name'];
1242
				}
1243
			}
1244
		}
1245
	}
1246

    
1247
	return $members;
1248
}
1249
?>
(24-24/65)