Project

General

Profile

Download (38.8 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
				$gateway['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
				if (is_linklocal($gateways_arr[$upgw]['gateway']) && get_ll_scope($gateways_arr[$upgw]['gateway']) == '') {
865
					$gateways_arr[$upgw]['gateway'] .= "%" . $gateways_arr[$upgw]['interface'];
866
				}
867
			} else {
868
				$inetfamily = "-inet";
869
			}
870
			mwexec("/sbin/route change {$inetfamily} default {$gateways_arr[$upgw]['gateway']}");
871
		}
872
	} else if (!empty($dfltgwname)) {
873
		$defaultgw = trim(exec("/sbin/route -n get -{$ipprotocol} default | /usr/bin/awk '/gateway:/ {print $2}'"), " \n");
874
		if ($ipprotocol == 'inet6' && !is_ipaddrv6($gateways_arr[$dfltgwname]['gateway'])) {
875
			return;
876
		}
877
		if ($ipprotocol == 'inet' && !is_ipaddrv4($gateways_arr[$dfltgwname]['gateway'])) {
878
			return;
879
		}
880
		if ($ipprotocol == 'inet6') {
881
			if (is_linklocal($gateways_arr[$upgw]['gateway']) && get_ll_scope($gateways_arr[$upgw]['gateway']) == '') {
882
				$gateways_arr[$upgw]['gateway'] .= "%" . $gateways_arr[$upgw]['interface'];
883
			}
884
			if (is_linklocal($gateways_arr[$dfltgwname]['gateway']) && get_ll_scope($gateways_arr[$dfltgwname]['gateway']) == '') {
885
				$gateways_arr[$dfltgwname]['gateway'] .= "%" . $gateways_arr[$dfltgwname]['interface'];
886
			}
887
		}
888
		if ($defaultgw != $gateways_arr[$dfltgwname]['gateway']) {
889
			mwexec("/sbin/route change -{$ipprotocol} default {$gateways_arr[$dfltgwname]['gateway']}");
890
		}
891
	}
892
}
893

    
894
/*
895
 * Return an array with all gateway groups with name as key
896
 * All gateway groups will be processed before returning the array.
897
 */
898
function return_gateway_groups_array() {
899
	global $config, $g;
900

    
901
	/* fetch the current gateways status */
902
	$gateways_status = return_gateways_status(true);
903
	$gateways_arr = return_gateways_array();
904
	$gateway_groups_array = array();
905

    
906
	if (isset($config['system']['gw_switch_default'])) {
907
		fixup_default_gateway("inet", $gateways_status, $gateways_arr);
908
		fixup_default_gateway("inet6", $gateways_status, $gateways_arr);
909
	}
910
	if (is_array($config['gateways']['gateway_group'])) {
911
		$viplist = get_configured_vip_list();
912
		foreach ($config['gateways']['gateway_group'] as $group) {
913
			$gateway_groups_array[$group['name']]['descr'] = $group['descr'];
914
			/* create array with group gateways members separated by tier */
915
			$tiers = array();
916
			$backupplan = array();
917
			$gwvip_arr = array();
918
			foreach ($group['item'] as $item) {
919
				list($gwname, $tier, $vipname) = explode("|", $item);
920

    
921
				if (is_ipaddr($viplist[$vipname])) {
922
					if (!is_array($gwvip_arr[$group['name']])) {
923
						$gwvip_arr[$group['name']] = array();
924
					}
925
					$gwvip_arr[$group['name']][$gwname] = $vipname;
926
				}
927

    
928
				/* Do it here rather than reiterating again the group in case no member is up. */
929
				if (!is_array($backupplan[$tier])) {
930
					$backupplan[$tier] = array();
931
				}
932
				$backupplan[$tier][] = $gwname;
933

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

    
979
			/* we do not really foreach the tiers as we stop after the first tier */
980
			foreach ($tiers as $tieridx => $tier) {
981
				/* process all gateways in this tier */
982
				foreach ($tier as $member) {
983
					/* determine interface gateway */
984
					if (isset($gateways_arr[$member])) {
985
						$gateway = $gateways_arr[$member];
986
						$int = $gateway['interface'];
987
						$gatewayip = "";
988
						if (is_ipaddr($gateway['gateway'])) {
989
							$gatewayip = $gateway['gateway'];
990
						} else if (!empty($int)) {
991
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
992
						}
993

    
994
						if (!empty($int)) {
995
							$gateway_groups_array[$group['name']]['ipprotocol'] = $gateway['ipprotocol'];
996
							if (is_ipaddr($gatewayip)) {
997
								$groupmember = array();
998
								$groupmember['int'] = $int;
999
								$groupmember['gwip'] = $gatewayip;
1000
								$groupmember['weight'] = isset($gateway['weight']) ? $gateway['weight'] : 1;
1001
								if (is_array($gwvip_arr[$group['name']]) && !empty($gwvip_arr[$group['name']][$member]))
1002
									$groupmember['vip'] = $gwvip_arr[$group['name']][$member];
1003
								$gateway_groups_array[$group['name']][] = $groupmember;
1004
							}
1005
						}
1006
					}
1007
				}
1008
				/* we should have the 1st available tier now, exit stage left */
1009
				if (count($gateway_groups_array[$group['name']]) > 0) {
1010
					break;
1011
				} else {
1012
					log_error(sprintf(gettext('GATEWAYS: Group %1$s did not have any gateways up on tier %2$s!'), $group['name'], $tieridx));
1013
				}
1014
			}
1015
		}
1016
	}
1017

    
1018
	return ($gateway_groups_array);
1019
}
1020

    
1021
/* Update DHCP WAN Interface ip address in gateway group item */
1022
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
1023
	global $config, $g;
1024
	foreach ($config['gateways']['gateway_item'] as & $gw) {
1025
		if ($gw['interface'] == $interface) {
1026
			$current_gw = get_interface_gateway($interface);
1027
			if ($gw['gateway'] <> $current_gw) {
1028
				$gw['gateway'] = $current_gw;
1029
				$changed = true;
1030
			}
1031
		}
1032
	}
1033
	if ($changed && $current_gw) {
1034
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interface, $current_gw));
1035
	}
1036
}
1037

    
1038
function lookup_gateway_ip_by_name($name, $disabled = false) {
1039

    
1040
	$gateways_arr = return_gateways_array($disabled, true);
1041
	foreach ($gateways_arr as $gname => $gw) {
1042
		if ($gw['name'] === $name || $gname === $name) {
1043
			return $gw['gateway'];
1044
		}
1045
	}
1046

    
1047
	return false;
1048
}
1049

    
1050
function lookup_gateway_monitor_ip_by_name($name) {
1051

    
1052
	$gateways_arr = return_gateways_array(false, true);
1053
	if (!empty($gateways_arr[$name])) {
1054
		$gateway = $gateways_arr[$name];
1055
		if (!is_ipaddr($gateway['monitor'])) {
1056
			return $gateway['gateway'];
1057
		}
1058

    
1059
		return $gateway['monitor'];
1060
	}
1061

    
1062
	return (false);
1063
}
1064

    
1065
function lookup_gateway_interface_by_name($name) {
1066

    
1067
	$gateways_arr = return_gateways_array(false, true);
1068
	if (!empty($gateways_arr[$name])) {
1069
		$interfacegw = $gateways_arr[$name]['friendlyiface'];
1070
		return ($interfacegw);
1071
	}
1072

    
1073
	return (false);
1074
}
1075

    
1076
function get_interface_gateway($interface, &$dynamic = false) {
1077
	global $config, $g;
1078

    
1079
	if (substr($interface, 0, 4) == '_vip') {
1080
		$interface = get_configured_vip_interface($interface);
1081
		if (substr($interface, 0, 4) == '_vip') {
1082
			$interface = get_configured_vip_interface($interface);
1083
		}
1084
	}
1085

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

    
1097
	// for dynamic interfaces we handle them through the $interface_router file.
1098
	if (($gw == NULL || !is_ipaddrv4($gw)) && !is_ipaddrv4($gwcfg['ipaddr'])) {
1099
		$realif = get_real_interface($interface);
1100
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
1101
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
1102
			$dynamic = true;
1103
		}
1104
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw")) {
1105
			$dynamic = "default";
1106
		}
1107

    
1108
	}
1109

    
1110
	/* return gateway */
1111
	return ($gw);
1112
}
1113

    
1114
function get_interface_gateway_v6($interface, &$dynamic = false) {
1115
	global $config, $g;
1116

    
1117
	if (substr($interface, 0, 4) == '_vip') {
1118
		$interface = get_configured_vip_interface($interface);
1119
		if (substr($interface, 0, 4) == '_vip') {
1120
			$interface = get_configured_vip_interface($interface);
1121
		}
1122
	}
1123

    
1124
	$gw = NULL;
1125
	$gwcfg = $config['interfaces'][$interface];
1126
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
1127
		foreach ($config['gateways']['gateway_item'] as $gateway) {
1128
			if (($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
1129
				$gw = $gateway['gateway'];
1130
				break;
1131
			}
1132
		}
1133
	}
1134

    
1135
	// for dynamic interfaces we handle them through the $interface_router file.
1136
	if (($gw == NULL || !is_ipaddrv6($gw)) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
1137
		$realif = get_real_interface($interface);
1138
		if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
1139
			$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
1140
			$dynamic = true;
1141
		}
1142
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6")) {
1143
			$dynamic = "default";
1144
		}
1145
	}
1146
	/* return gateway */
1147
	return ($gw);
1148
}
1149

    
1150
/* Check a IP address against a gateway IP or name
1151
 * to verify it's address family */
1152
function validate_address_family($ipaddr, $gwname, $disabled = false) {
1153
	$v4ip = false;
1154
	$v6ip = false;
1155
	$v4gw = false;
1156
	$v6gw = false;
1157

    
1158
	if (is_ipaddrv4($ipaddr)) {
1159
		$v4ip = true;
1160
	}
1161
	if (is_ipaddrv6($ipaddr)) {
1162
		$v6ip = true;
1163
	}
1164
	if (is_ipaddrv4($gwname)) {
1165
		$v4gw = true;
1166
	}
1167
	if (is_ipaddrv6($gwname)) {
1168
		$v6gw = true;
1169
	}
1170

    
1171
	if ($v4ip && $v4gw) {
1172
		return true;
1173
	}
1174
	if ($v6ip && $v6gw) {
1175
		return true;
1176
	}
1177

    
1178
	/* still no match, carry on, lookup gateways */
1179
	if (is_ipaddrv4(lookup_gateway_ip_by_name($gwname, $disabled))) {
1180
		$v4gw = true;
1181
	}
1182
	if (is_ipaddrv6(lookup_gateway_ip_by_name($gwname, $disabled))) {
1183
		$v6gw = true;
1184
	}
1185

    
1186
	$gw_array = return_gateways_array();
1187
	if (is_array($gw_array[$gwname])) {
1188
		switch ($gw_array[$gwname]['ipprotocol']) {
1189
			case "inet":
1190
				$v4gw = true;
1191
				break;
1192
			case "inet6":
1193
				$v6gw = true;
1194
				break;
1195
		}
1196
	}
1197

    
1198
	if ($v4ip && $v4gw) {
1199
		return true;
1200
	}
1201
	if ($v6ip && $v6gw) {
1202
		return true;
1203
	}
1204

    
1205
	return false;
1206
}
1207

    
1208
/* check if a interface is part of a gateway group */
1209
function interface_gateway_group_member($interface) {
1210
	global $config;
1211

    
1212
	if (is_array($config['gateways']['gateway_group'])) {
1213
		$groups = $config['gateways']['gateway_group'];
1214
	} else {
1215
		return false;
1216
	}
1217

    
1218
	$gateways_arr = return_gateways_array(false, true);
1219
	foreach ($groups as $group) {
1220
		if (is_array($group['item'])) {
1221
			foreach ($group['item'] as $item) {
1222
				$elements = explode("|", $item);
1223
				$gwname = $elements[0];
1224
				if ($interface == $gateways_arr[$gwname]['interface']) {
1225
					unset($gateways_arr);
1226
					return true;
1227
				}
1228
			}
1229
		}
1230
	}
1231
	unset($gateways_arr);
1232

    
1233
	return false;
1234
}
1235

    
1236
function gateway_is_gwgroup_member($name) {
1237
	global $config;
1238

    
1239
	if (is_array($config['gateways']['gateway_group'])) {
1240
		$groups = $config['gateways']['gateway_group'];
1241
	} else {
1242
		return false;
1243
	}
1244

    
1245
	$members = array();
1246
	foreach ($groups as $group) {
1247
		if (is_array($group['item'])) {
1248
			foreach ($group['item'] as $item) {
1249
				$elements = explode("|", $item);
1250
				$gwname = $elements[0];
1251
				if ($name == $elements[0]) {
1252
					$members[] = $group['name'];
1253
				}
1254
			}
1255
		}
1256
	}
1257

    
1258
	return $members;
1259
}
1260
?>
(24-24/65)