Project

General

Profile

Download (22.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
  Copyright (C) 2008 Bill Marquette, Seth Mos
4
  Copyright (C) 2010 Ermal Lu?i
5
  All rights reserved.
6

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

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

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

    
17
  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19
  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20
  AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
  POSSIBILITY OF SUCH DAMAGE.
27

    
28
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/sbin/route	/usr/local/sbin/apinger
29
	pfSense_MODULE:	routing
30

    
31
 */
32

    
33
/*
34
 * Creates monitoring configuration file and
35
 * adds apropriate static routes.
36
 */
37
function setup_gateways_monitor() {
38
	global $config, $g;
39

    
40
	$gateways_arr = return_gateways_array();
41
	if (!is_array($gateways_arr)) {
42
		log_error("No gateways to monitor. Apinger will not be run.");
43
		killbypid("{$g['varrun_path']}/apinger.pid");
44
		@unlink("{$g['tmp_path']}/apinger.status");
45
		return;
46
	}
47

    
48
	/* Default settings. Probably should move to globals.inc? */
49
	$a_settings = array();
50
	$a_settings['latencylow'] = "200";
51
	$a_settings['latencyhigh'] = "500";
52
	$a_settings['losslow'] = "10";
53
	$a_settings['losshigh'] = "20";
54

    
55
	$fd = fopen("{$g['varetc_path']}/apinger.conf", "w");
56
	$apingerconfig = <<<EOD
57

    
58
# pfSense apinger configuration file. Automatically Generated!
59

    
60
## User and group the pinger should run as
61
user "root"
62
group "wheel"
63

    
64
## Mailer to use (default: "/usr/lib/sendmail -t")
65
#mailer "/var/qmail/bin/qmail-inject" 
66

    
67
## Location of the pid-file (default: "/var/run/apinger.pid")
68
pid_file "{$g['varrun_path']}/apinger.pid"
69

    
70
## Format of timestamp (%s macro) (default: "%b %d %H:%M:%S")
71
#timestamp_format "%Y%m%d%H%M%S"
72

    
73
status {
74
	## File where the status information whould be written to
75
	file "{$g['tmp_path']}/apinger.status"
76
	## Interval between file updates
77
	## when 0 or not set, file is written only when SIGUSR1 is received
78
	interval 5s
79
}
80

    
81
########################################
82
# RRDTool status gathering configuration
83
# Interval between RRD updates
84
rrd interval 60s;
85

    
86
## These parameters can be overriden in a specific alarm configuration
87
alarm default { 
88
	command on "/usr/local/sbin/pfSctl -c 'filter reload'"
89
	command off "/usr/local/sbin/pfSctl -c 'filter reload'"
90
	combine 10s
91
}
92

    
93
## "Down" alarm definition. 
94
## This alarm will be fired when target doesn't respond for 30 seconds.
95
alarm down "down" {
96
	time 10s
97
}
98

    
99
## "Delay" alarm definition. 
100
## This alarm will be fired when responses are delayed more than 200ms
101
## it will be canceled, when the delay drops below 100ms
102
alarm delay "delay" {
103
	delay_low {$a_settings['latencylow']}ms
104
	delay_high {$a_settings['latencyhigh']}ms
105
}
106

    
107
## "Loss" alarm definition. 
108
## This alarm will be fired when packet loss goes over 20%
109
## it will be canceled, when the loss drops below 10%
110
alarm loss "loss" {
111
	percent_low {$a_settings['losslow']}
112
	percent_high {$a_settings['losshigh']}
113
}
114

    
115
target default {
116
	## How often the probe should be sent	
117
	interval 1s
118
	
119
	## How many replies should be used to compute average delay 
120
	## for controlling "delay" alarms
121
	avg_delay_samples 10
122
	
123
	## How many probes should be used to compute average loss
124
	avg_loss_samples 50
125

    
126
	## The delay (in samples) after which loss is computed
127
	## without this delays larger than interval would be treated as loss
128
	avg_loss_delay_samples 20
129

    
130
	## Names of the alarms that may be generated for the target
131
	alarms "down","delay","loss"
132

    
133
	## Location of the RRD
134
	#rrd file "{$g['vardb_path']}/rrd/apinger-%t.rrd"
135
}
136

    
137
EOD;
138

    
139
	foreach($gateways_arr as $name => $gateway) {
140
		/* Do not monitor if such was requested */
141
		if (isset($gateway['monitor_disable']))
142
			continue;
143
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
144
			if (is_ipaddr($gateway['gateway']))
145
				$gateway['monitor'] = $gateway['gateway'];
146
			else /* No chance to get an ip to monitor skip target. */
147
				continue;
148
		}
149

    
150
		/* Interface ip is needed since apinger will bind a socket to it. */
151
		if (is_ipaddrv4($gateway['gateway'])) {
152
			$gwifip = find_interface_ip($gateway['interface'], true);
153
		}
154
		if (is_ipaddrv6($gateway['gateway'])) {
155
			$gwifip = find_interface_ipv6($gateway['interface'], true);
156
		}
157
		if (!is_ipaddr($gwifip))
158
			continue; //Skip this target
159

    
160
		$apingercfg = "target \"{$gateway['monitor']}\" {\n";
161
		$apingercfg .= "	description \"{$name}\"\n";
162
		$apingercfg .= "	srcip \"{$gwifip}\"\n";
163
		if (!empty($gateway['interval']) && intval($gateway['interval']) > 1)
164
			$apingercfg .= "	interval " . intval($gateway['interval']) . "s\n";
165
		$alarms = "";
166
		$alarmscfg = "";
167
		$override = false;
168
		if (!empty($gateway['lowloss'])) {
169
			$alarmscfg .= "alarm loss \"{$name}loss\" {\n";
170
			$alarmscfg .= "\tpercent_low {$gateway['losslow']}\n";
171
       			$alarmscfg .= "\tpercent_high {$gateway['losshigh']}\n";
172
			$alarmscfg .= "}\n";
173
			$alarms .= "\"{$name}loss\"";
174
			$override = true;
175
		} else {
176
			if ($override == true)
177
				$alarms .= ",";
178
			$alarms .= "\"loss\"";
179
			$override = true;
180
		}
181
		if (!empty($gateway['latencylow'])) {
182
			$alarmscfg .= "alarm delay \"{$name}delay\" {\n";
183
			$alarmscfg .= "\tdelay_low {$gateway['latencylow']}ms\n";
184
			$alarmscfg .= "\tdelay_high {$gateway['latencyhigh']}ms\n";
185
			$alarmscfg .= "}\n";
186
			if ($override == true)
187
				$alarms .= ",";
188
			$alarms .= "\"{$name}delay\"";
189
			$override = true;
190
		} else {
191
			if ($override == true)
192
				$alarms .= ",";
193
			$alarms .= "\"delay\"";
194
			$override = true;
195
		}
196
		if (!empty($gateway['down'])) {
197
			$alarmscfg .= "alarm down \"{$name}down\" {\n";
198
			$alarmscfg .= "\ttime {$gateway['down']}s\n";
199
			$alarmscfg .= "}\n";
200
			if ($override == true)
201
				$alarms .= ",";
202
			$alarms .= "\"{$name}down\"";
203
			$override = true;
204
		} else {
205
			if ($override == true)
206
				$alarms .= ",";
207
			$alarms .= "\"down\"";
208
			$override = true;
209
		}
210
		if ($override == true)
211
			$apingercfg .= "\talarms override {$alarms};\n";
212

    
213
		$apingercfg .= "	rrd file \"{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd\"\n";
214
		$apingercfg .= "}\n";
215
		$apingercfg .= "\n";
216
		/*
217
		 * If the gateway is the same as the monitor we do not add a
218
		 * route as this will break the routing table.
219
		 * Add static routes for each gateway with their monitor IP
220
		 * not strictly necessary but is a added level of protection.
221
		 */
222
		if (is_ipaddr($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
223
			log_error(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $gateway['gateway']));
224
			mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
225
				" " . escapeshellarg($gateway['gateway']), true);
226
		}
227

    
228
		$apingerconfig .= $alarmscfg;
229
		$apingerconfig .= $apingercfg;
230
	}
231
	fwrite($fd, $apingerconfig);
232
	fclose($fd);
233

    
234
	killbypid("{$g['varrun_path']}/apinger.pid");
235
	if (is_dir("{$g['tmp_path']}"))
236
		chmod("{$g['tmp_path']}", 01777);
237
	if (!is_dir("{$g['vardb_path']}/rrd"))
238
		mkdir("{$g['vardb_path']}/rrd", 0775);
239

    
240
	@chown("{$g['vardb_path']}/rrd", "nobody");
241

    
242
	/* start a new apinger process */
243
	@unlink("{$g['tmp_path']}/apinger.status");
244
	sleep(1);
245
	mwexec_bg("/usr/local/sbin/apinger -c {$g['varetc_path']}/apinger.conf");
246

    
247
	return 0;
248
}
249

    
250
/* return the status of the apinger targets as a array */
251
function return_gateways_status($byname = false) {
252
	global $config, $g;
253

    
254
	$apingerstatus = array();
255
	if (file_exists("{$g['tmp_path']}/apinger.status")) {
256
		$apingerstatus = file("{$g['tmp_path']}/apinger.status");
257
	}
258

    
259
	$status = array();
260
	foreach($apingerstatus as $line) {
261
		$info = explode("|", $line);
262
		if ($byname == false)
263
			$target = $info[0];
264
		else
265
			$target = $info[2];
266
		$status[$target]['monitorip'] = $info[0];
267
		$status[$target]['srcip'] = $info[1];
268
		$status[$target]['name'] = $info[2];
269
		$status[$target]['lastcheck'] = $info[5] ? date('r', $info[5]) : date('r');
270
		$status[$target]['delay'] = empty($info[6]) ? 0 : $info[6];
271
		$status[$target]['loss'] = empty($info[7]) ? "0.0%" : $info[7] . "";
272
		$status[$target]['status'] = trim($info[8]);
273
	}
274

    
275
	return($status);
276
}
277

    
278
/* Return all configured gateways on the system */
279
function return_gateways_array($disabled = false) {
280
	global $config, $g;
281

    
282
	$gateways_arr = array();
283

    
284
	$i = 0;
285
	/* Process/add all the configured gateways. */
286
	if (is_array($config['gateways']['gateway_item'])) {
287
		foreach($config['gateways']['gateway_item'] as $gateway) {
288
			if(empty($gateway['gateway']) || preg_match("/dynamic/", $gateway['gateway'])) {
289
				$gateway['gateway'] = get_interface_gateway($gateway['interface']);
290
				if(preg_match("/dynamic/", $gateway['gateway'])) {
291
					$dynstr = $gateway['gateway'];
292
				}
293
				/* no IP address found, set to dynamic */
294
				if(! is_ipaddr($gateway['gateway'])) {
295
					$gateway['gateway'] = "{$dynstr}";
296
				}
297
				$gateway['dynamic'] = true;
298
			}
299
			if(is_ipaddrv4($gateway['gateway']))
300
				$gateway['ipprotocol'] = "inet";
301
			if(is_ipaddrv6($gateway['gateway']))
302
				$gateway['ipprotocol'] = "inet6";
303
			if (isset($gateway['monitor_disable']))
304
				$gateway['monitor_disable'] = true;
305
			else if (empty($gateway['monitor']))
306
				$gateway['monitor'] = $gateway['gateway'];
307

    
308
			$gateway['friendlyiface'] = $gateway['interface'];
309
			$gateway['interface'] = get_real_interface($gateway['interface']);
310
			/* FIXME: Should this be enabled.
311
			 * Some interface like wan might be default but have no info recorded 
312
			 * the config.
313
			if ($gateway['friendlyiface'] == "wan" && !isset($gateway['defaultgw'])) {
314
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw"))
315
					$gateway['defaultgw'] = true;
316
			}
317
			 */
318
			/* include the gateway index as the attribute */
319
			$gateway['attribute'] = $i;
320

    
321
			$gateways_arr[$gateway['name']] = $gateway;
322
			$i++;
323
		}
324
	} 
325

    
326
	/* Loop through all interfaces with a gateway and add it to a array */
327
	if ($disabled == false)
328
		$iflist = get_configured_interface_with_descr();
329
	else
330
		$iflist = get_configured_interface_with_descr(false, true);
331

    
332
	/* Process/add dynamic v4 gateways. */
333
	foreach($iflist as $ifname => $friendly ) {
334
		if(! interface_has_gateway($ifname))
335
			continue;
336

    
337
		if (empty($config['interfaces'][$ifname]))
338
			continue;
339

    
340
		$ifcfg = &$config['interfaces'][$ifname];
341
		if(!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr']))
342
			continue;
343

    
344
		$gateway = array();
345
		$gateway['dynamic'] = false;
346
		$gateway['ipprotocol'] = "inet";
347
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
348
		$gateway['interface'] = get_real_interface($ifname);
349
		$gateway['friendlyiface'] = $ifname;
350
		$gateway['name'] = $friendly;
351
		$gateway['attribute'] = "system";
352
	
353
		if ($gateway['dynamic'] === "default") {
354
			$gateway['defaultgw'] = true;
355
			$gateway['dynamic'] = true;
356
		}
357
		/* Loopback dummy for dynamic interfaces without a IP */
358
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true)
359
			$gateway['gateway'] = "dynamic";
360

    
361
		/* automatically skip known static and dynamic gateways we have a array entry for */
362
		foreach($gateways_arr as $gateway_item) {
363
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
364
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
365
					continue 2;
366
		}
367

    
368
		if (is_ipaddrv4($gateway['gateway']))
369
			$gateway['monitor'] = $gateway['gateway'];
370

    
371
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
372
		$gateways_arr[$gateway['name']] = $gateway;
373
	}
374

    
375
	/* Process/add dynamic v6 gateways. */
376
	foreach($iflist as $ifname => $friendly ) {
377
		if(! interface_has_gatewayv6($ifname))
378
			continue;
379

    
380
		if (empty($config['interfaces'][$ifname]))
381
			continue;
382

    
383
		$ifcfg = &$config['interfaces'][$ifname];
384
		if(!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
385
			continue;
386

    
387
		$gateway = array();
388
		$gateway['dynamic'] = false;
389
		$gateway['ipprotocol'] = "inet6";
390
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
391
		$gateway['interface'] = get_real_interface($ifname);
392
		$gateway['friendlyiface'] = $ifname;
393
		$gateway['name'] = "{$friendly}_v6";
394
		$gateway['attribute'] = "system";
395
	
396
		if ($gateway['dynamic'] === "default") {
397
			$gateway['defaultgw'] = true;
398
			$gateway['dynamic'] = true;
399
		}
400

    
401
		/* Loopback dummy for dynamic interfaces without a IP */
402
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true)
403
			$gateway['gateway'] = "dynamic6";
404

    
405
		/* automatically skip known static and dynamic gateways we have a array entry for */
406
		foreach($gateways_arr as $gateway_item) {
407
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
408
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
409
					continue 2;
410
		}
411

    
412
		if (is_ipaddrv6($gateway['gateway']))
413
			$gateway['monitor'] = $gateway['gateway'];
414

    
415
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
416
		$gateways_arr[$gateway['name']] = $gateway;
417
	}
418
	return($gateways_arr);
419
}
420

    
421
/*
422
 * Return an array with all gateway groups with name as key
423
 * All gateway groups will be processed before returning the array.
424
 */
425
function return_gateway_groups_array() {
426
	global $config, $g;
427

    
428
	/* fetch the current gateways status */
429
	$gateways_status = return_gateways_status(true);
430
	$gateways_arr = return_gateways_array();
431
	$gateway_groups_array = array();
432

    
433
	if (isset($config['system']['gw_switch_default'])) {
434
		/* 
435
		 * NOTE: The code below is meant to replace the default gateway when it goes down.
436
		 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
437
		 */
438
		$upgw = "";
439
		$dfltgwdown = false;
440
		$dfltgwfound = false;
441
		foreach ($gateways_arr as $gwname => $gwsttng) {
442
			if (isset($gwsttng['defaultgw'])) {
443
				$dfltgwfound = true;
444
				$dfltgwname = $gwname;
445
				if (!isset($gwsttng['monitor_disable']) && stristr($gateways_status[$gwname]['status'], "down"))
446
					$dfltgwdown = true;
447
			}
448
			/* Keep a record of the last up gateway */
449
			/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
450
			if (empty($upgw) && (isset($gwsttng['monitor_disable']) || !stristr($gateways_status[$gwname]['status'], "down")) && $gwsttng[$gwname]['friendlyiface'] != "lan")
451
				$upgw = $gwname;
452
			if ($dfltgwdown == true && !empty($upgw))
453
				break;
454
		}
455
		if ($dfltgwfound == false) {
456
			$gwname = convert_friendly_interface_to_friendly_descr("wan");
457
			if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down"))
458
				$dfltgwdown = true;
459
		}
460
		if ($dfltgwdown == true && !empty($upgw)) {
461
			if (preg_match("/dynamic", $gateways_arr[$upgw]['gateway']))
462
				$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
463
			if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
464
				log_error("Default gateway down setting {$upgw} as default!");
465
				mwexec("/sbin/route change -inet default {$gateways_arr[$upgw]['gateway']}");
466
			}
467
		} else {
468
			$defaultgw = trim(`/sbin/route -n get -inet default | /usr/bin/grep gateway | /usr/bin/sed 's/gateway://g'`, " \n");
469
			if ($defaultgw != $gateways_arr[$dfltgwname]['gateway'])
470
				mwexec("/sbin/route change -inet default {$gateways_arr[$dfltgwname]['gateway']}");
471
		}
472
				
473
		unset($upgw, $dfltgwfound, $dfltgwdown, $gwname, $gwsttng);
474
	}
475

    
476
	if (is_array($config['gateways']['gateway_group'])) {
477
		foreach($config['gateways']['gateway_group'] as $group) {
478
			/* create array with group gateways members seperated by tier */
479
			$tiers = array();
480
			$backupplan = array();
481
			foreach($group['item'] as $item) {
482
				$itemsplit = explode("|", $item);
483
				$tier = $itemsplit[1];
484
				$gwname = $itemsplit[0];
485

    
486
				/* Do it here rather than reiterating again the group in case no member is up. */
487
				$backupplan[$tier][] = $gwname;
488

    
489
				/* check if the gateway is available before adding it to the array */
490
				if (!empty($gateways_status[$gwname])) {
491
					$status = $gateways_status[$gwname];
492
					$gwdown = false;
493
					if (stristr($status['status'], "down")) {
494
						$msg = sprintf(gettext("MONITOR: %s is down, removing from routing group"), $gwname);
495
						$gwdown = true;
496
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
497
						/* packet loss */
498
						$msg = sprintf(gettext("MONITOR: %s has packet loss, removing from routing group"), $gwname);
499
						$gwdown = true;
500
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
501
						/* high latency */
502
						$msg = sprintf(gettext("MONITOR: %s has high latency, removing from routing group"), $gwname);
503
						$gwdown = true;
504
					}
505
					if ($gwdown == true) {
506
						log_error($msg);
507
						notify_via_growl($msg);
508
						notify_via_smtp($msg);
509
					} else
510
						/* Online add member */
511
						$tiers[$tier][] = $gwname;
512
				} else if (isset($gateways_arr[$gwname]['monitor_disable']))
513
					$tiers[$tier][] = $gwname;
514
			}
515
			$tiers_count = count($tiers);
516
			if($tiers_count == 0) {
517
				/* Oh dear, we have no members! Engage Plan B */
518
				if (!$g['booting']) {
519
					$msg = gettext("Gateways status could not be determined, considering all as up/active.");
520
					log_error($msg);
521
					notify_via_growl($msg);
522
					notify_via_smtp($msg);
523
				}
524
				$tiers = $backupplan;
525
			}
526
			/* sort the tiers array by the tier key */
527
			ksort($tiers);
528

    
529
			/* we do not really foreach the tiers as we stop after the first tier */
530
			foreach($tiers as $tier) {
531
				/* process all gateways in this tier */
532
				foreach($tier as $member) {
533
					/* determine interface gateway */
534
					if (isset($gateways_arr[$member])) {
535
						$gateway = $gateways_arr[$member];
536
						$int = $gateway['interface'];
537
						$gatewayip = "";
538
						if(is_ipaddr($gateway['gateway'])) 
539
							$gatewayip = $gateway['gateway'];
540
						else if ($int <> "")
541
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
542
					
543
						if (($int <> "") && is_ipaddr($gatewayip)) {
544
							$groupmember = array();
545
							$groupmember['int']  = $int;
546
							$groupmember['gwip']  = $gatewayip;
547
							$groupmember['weight']  = isset($gateway['weight']) ? $gateway['weight'] : 1;
548
							$gateway_groups_array[$group['name']][] = $groupmember;
549
						}
550
					}
551
				}
552
				/* we should have the 1st available tier now, exit stage left */
553
				break;
554
			}
555
		}
556
	}
557
	return ($gateway_groups_array);
558
}
559

    
560
/* Update DHCP WAN Interface ip address in gateway group item */
561
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
562
	global $config, $g;
563
	foreach($config['gateways']['gateway_item'] as & $gw) {	
564
		if($gw['interface'] == $interface) {
565
			$current_gw = get_interface_gateway($interface);
566
			if($gw['gateway'] <> $current_gw) {
567
				$gw['gateway'] = $current_gw;
568
				$changed = true;
569
			}
570
		}
571
	}
572
	if($changed && $current_gw)
573
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
574
}
575

    
576
function lookup_gateway_ip_by_name($name) {
577

    
578
	$gateways_arr = return_gateways_array();
579
        foreach ($gateways_arr as $gname => $gw) {
580
                if ($gw['name'] == $name || $gname == $name)
581
                        return $gw['gateway'];
582
        }
583

    
584
	return false;
585
}
586

    
587
function lookup_gateway_monitor_ip_by_name($name) {
588

    
589
        $gateways_arr = return_gateways_array();
590
	if (!empty($gateways_arr[$name])) {
591
		$gateway = $gateways_arr[$name];
592
		if(!is_ipaddr($gateway['monitor']))
593
			return $gateway['gateway'];
594

    
595
		return $gateway['monitor'];
596
        }
597

    
598
        return (false);
599
}
600

    
601
function lookup_gateway_interface_by_name($name) {
602

    
603
        $gateways_arr = return_gateways_array();
604
	if (!empty($gateways_arr[$name])) {
605
		$interfacegw = $gateway['interface'];
606
		return ($interfacegw);
607
        }
608

    
609
        return (false);
610
}
611

    
612
function get_interface_gateway($interface, &$dynamic = false) {
613
	global $config, $g;
614

    
615
	$gw = NULL;
616

    
617
	$gwcfg = $config['interfaces'][$interface];
618
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
619
		foreach($config['gateways']['gateway_item'] as $gateway) {
620
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
621
				$gw = $gateway['gateway'];
622
				break;
623
			}
624
		}
625
	}
626

    
627
	// for dynamic interfaces we handle them through the $interface_router file.
628
	if (!is_ipaddrv4($gw) && !is_ipaddrv4($gwcfg['ipaddr'])) {
629
		$realif = get_real_interface($interface);
630
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
631
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
632
			$dynamic = true;
633
		}
634
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
635
			$dynamic = "default";
636
			
637
	}
638

    
639
	/* return gateway */
640
	return ($gw);
641
}
642

    
643
function get_interface_gateway_v6($interface, &$dynamic = false) {
644
	global $config, $g;
645

    
646
	$gw = NULL;
647
	$gwcfg = $config['interfaces'][$interface];
648
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
649
		foreach($config['gateways']['gateway_item'] as $gateway) {
650
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
651
				$gw = $gateway['gateway'];
652
				break;
653
			}
654
		}
655
	}
656

    
657
	// for dynamic interfaces we handle them through the $interface_router file.
658
	if (!is_ipaddrv6($gw) && !is_ipaddrv6($gwcfg['ipaddrv6'])) {
659
			$realif = get_real_interface($interface);
660
			if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
661
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
662
				$dynamic = true;
663
			}
664
			if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6"))
665
				$dynamic = "default";
666
			
667
	}
668
	/* return gateway */
669
	return ($gw);
670
}
671

    
672
/* Check a IP address against a gateway IP or name
673
 * to verify it's address family */
674
function validate_address_family($ipaddr, $gwname) {
675
	$v4ip = false;
676
	$v6ip = false;
677
	$v4gw = false;
678
	$v6gw = false;
679

    
680
	if(is_ipaddrv4($ipaddr))
681
		$v4ip = true;
682
	if(is_ipaddrv6($ipaddr))
683
		$v6ip = true;
684
	if(is_ipaddrv4($gwname))
685
		$v4gw = true;
686
	if(is_ipaddrv6($gwname))
687
		$v6gw = true;
688

    
689
	if($v4ip && $v4gw)
690
		return true;
691
	if($v6ip && $v6gw)
692
		return true;
693

    
694
	/* still no match, carry on, lookup gateways */
695
	if(is_ipaddrv4(lookup_gateway_ip_by_name($gwname)))
696
		$v4gw = true;
697
	if(is_ipaddrv6(lookup_gateway_ip_by_name($gwname)))
698
		$v6gw = true;
699
	/* are they dynamic */
700
	switch($gwname) {
701
		case "dynamic":
702
			$v4gw = true;
703
			break;
704
		case "dynamic6":
705
			$v6gw = true;
706
			break;
707
	}
708

    
709
	if($v4ip && $v4gw)
710
		return true;
711
	if($v6ip && $v6gw)
712
		return true;
713
	
714
	return false;
715
}
716

    
717

    
718
?>
(24-24/61)