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" => "500",
65
		"loss_interval" => "2000",
66
		"time_period" => "60000",
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(sprintf(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
			$gateway_groups_array[$group['name']]['descr'] = $group['descr'];
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: %1$s is down, omitting from routing group %2$s'), $gwname, $group['name']);
929
						$gwdown = true;
930
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
931
						/* packet loss */
932
						$msg = sprintf(gettext('MONITOR: %1$s has packet loss, omitting from routing group %2$s'), $gwname, $group['name']);
933
						$gwdown = true;
934
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
935
						/* high latency */
936
						$msg = sprintf(gettext('MONITOR: %1$s has high latency, omitting from routing group %2$s'), $gwname, $group['name']);
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 = sprintf(gettext('Gateways status could not be determined, considering all as up/active. (Group: %s)'), $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(sprintf(gettext('GATEWAYS: Group %1$s did not have any gateways up on tier %2$s!'), $group['name'], $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'), $interface, $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)