Project

General

Profile

Download (38.2 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(gettext("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(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $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(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $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(sprintf(gettext("Error starting gateway monitor for %s"), $gateway['name']));
322
		}
323
	}
324

    
325
	return;
326
}
327

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

    
331
	$running_processes = running_dpinger_processes();
332

    
333
	if (!isset($running_processes[$gwname])) {
334
		log_error(sprint(gettext('dpinger: No dpinger session running for gateway %s'), $gwname));
335
		return false;
336
	}
337

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

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

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

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

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

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

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

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

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

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

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

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

    
408
	return $r;
409
}
410

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

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

    
418
	$gateways_arr = return_gateways_array();
419

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
982
						if (!empty($int)) {
983
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
984
							if (is_ipaddr($gatewayip)) {
985
								$groupmember = array();
986
								$groupmember['int'] = $int;
987
								$groupmember['gwip'] = $gatewayip;
988
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
989
								if (is_array($gwvip_arr[$group['name']]) && !empty($gwvip_arr[$group['name']][$member]))
990
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
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(sprintf(gettext('GATEWAYS: Group %1$s did not have any gateways up on tier %2$s!'), $group['name'], $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'), $interface, $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_vip_interface($interface);
1069
		if (substr($interface, 0, 4) == '_vip') {
1070
			$interface = get_configured_vip_interface($interface);
1071
		}
1072
	}
1073

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

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

    
1096
	}
1097

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

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

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

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

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

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

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

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

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

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

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

    
1193
	return false;
1194
}
1195

    
1196
/* check if a interface is part of a gateway group */
1197
function interface_gateway_group_member($interface) {
1198
	global $config;
1199

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

    
1206
	$gateways_arr = return_gateways_array(false, true);
1207
	foreach ($groups as $group) {
1208
		if (is_array($group['item'])) {
1209
			foreach ($group['item'] as $item) {
1210
				$elements = explode("|", $item);
1211
				$gwname = $elements[0];
1212
				if ($interface == $gateways_arr[$gwname]['interface']) {
1213
					unset($gateways_arr);
1214
					return true;
1215
				}
1216
			}
1217
		}
1218
	}
1219
	unset($gateways_arr);
1220

    
1221
	return false;
1222
}
1223

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

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

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

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