Project

General

Profile

Download (23.2 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
			/* link locals really need a different src ip */
156
			if(preg_match("/fe80::/i", $gateway['gateway'])) {
157
				$linklocal = explode("%", find_interface_ipv6_ll($gateway['interface'], true));
158
				$gwifip = $linklocal[0];
159
				$ifscope = "%". $linklocal[1];
160
			} else {
161
				$gwifip = find_interface_ipv6($gateway['interface'], true);
162
			}
163
		}
164
		if (!is_ipaddr($gwifip))
165
			continue; //Skip this target
166

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

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

    
235
		$apingerconfig .= $alarmscfg;
236
		$apingerconfig .= $apingercfg;
237
	}
238
	fwrite($fd, $apingerconfig);
239
	fclose($fd);
240

    
241
	killbypid("{$g['varrun_path']}/apinger.pid");
242
	if (is_dir("{$g['tmp_path']}"))
243
		chmod("{$g['tmp_path']}", 01777);
244
	if (!is_dir("{$g['vardb_path']}/rrd"))
245
		mkdir("{$g['vardb_path']}/rrd", 0775);
246

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

    
249
	/* start a new apinger process */
250
	@unlink("{$g['tmp_path']}/apinger.status");
251
	sleep(1);
252
	mwexec_bg("/usr/local/sbin/apinger -c {$g['varetc_path']}/apinger.conf");
253

    
254
	return 0;
255
}
256

    
257
/* return the status of the apinger targets as a array */
258
function return_gateways_status($byname = false) {
259
	global $config, $g;
260

    
261
	$apingerstatus = array();
262
	if (file_exists("{$g['tmp_path']}/apinger.status")) {
263
		$apingerstatus = file("{$g['tmp_path']}/apinger.status");
264
	}
265

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

    
282
	return($status);
283
}
284

    
285
/* Return all configured gateways on the system */
286
function return_gateways_array($disabled = false) {
287
	global $config, $g;
288

    
289
	$gateways_arr = array();
290

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

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

    
328
			$gateways_arr[$gateway['name']] = $gateway;
329
			$i++;
330
		}
331
	} 
332

    
333
	/* Loop through all interfaces with a gateway and add it to a array */
334
	if ($disabled == false)
335
		$iflist = get_configured_interface_with_descr();
336
	else
337
		$iflist = get_configured_interface_with_descr(false, true);
338

    
339
	/* Process/add dynamic v4 gateways. */
340
	foreach($iflist as $ifname => $friendly ) {
341
		if(! interface_has_gateway($ifname))
342
			continue;
343

    
344
		if (empty($config['interfaces'][$ifname]))
345
			continue;
346

    
347
		$ifcfg = &$config['interfaces'][$ifname];
348
		if(!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr']))
349
			continue;
350

    
351
		$gateway = array();
352
		$gateway['dynamic'] = false;
353
		$gateway['ipprotocol'] = "inet";
354
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
355
		$gateway['interface'] = get_real_interface($ifname);
356
		$gateway['friendlyiface'] = $ifname;
357
		$gateway['name'] = $friendly;
358
		$gateway['attribute'] = "system";
359
	
360
		if ($gateway['dynamic'] === "default") {
361
			$gateway['defaultgw'] = true;
362
			$gateway['dynamic'] = true;
363
		}
364
		/* Loopback dummy for dynamic interfaces without a IP */
365
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true)
366
			$gateway['gateway'] = "dynamic";
367

    
368
		/* automatically skip known static and dynamic gateways we have a array entry for */
369
		foreach($gateways_arr as $gateway_item) {
370
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
371
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
372
					continue 2;
373
		}
374

    
375
		if (is_ipaddrv4($gateway['gateway']))
376
			$gateway['monitor'] = $gateway['gateway'];
377

    
378
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
379
		$gateways_arr[$gateway['name']] = $gateway;
380
	}
381

    
382
	/* Process/add dynamic v6 gateways. */
383
	foreach($iflist as $ifname => $friendly ) {
384
		if(! interface_has_gatewayv6($ifname))
385
			continue;
386

    
387
		if (empty($config['interfaces'][$ifname]))
388
			continue;
389

    
390
		$ifcfg = &$config['interfaces'][$ifname];
391
		if(!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
392
			continue;
393

    
394
		$gateway = array();
395
		$gateway['dynamic'] = false;
396
		$gateway['ipprotocol'] = "inet6";
397
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
398
		$gateway['interface'] = get_real_interface($ifname);
399
		$gateway['friendlyiface'] = $ifname;
400
		$gateway['name'] = "{$friendly}_v6";
401
		$gateway['attribute'] = "system";
402
	
403
		if ($gateway['dynamic'] === "default") {
404
			$gateway['defaultgw'] = true;
405
			$gateway['dynamic'] = true;
406
		}
407

    
408
		/* Loopback dummy for dynamic interfaces without a IP */
409
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true)
410
			$gateway['gateway'] = "dynamic6";
411

    
412
		/* automatically skip known static and dynamic gateways we have a array entry for */
413
		foreach($gateways_arr as $gateway_item) {
414
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
415
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
416
					continue 2;
417
		}
418

    
419
		if (is_ipaddrv6($gateway['gateway']))
420
			$gateway['monitor'] = $gateway['gateway'];
421

    
422
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
423
		$gateways_arr[$gateway['name']] = $gateway;
424
	}
425
	return($gateways_arr);
426
}
427

    
428
/*
429
 * Return an array with all gateway groups with name as key
430
 * All gateway groups will be processed before returning the array.
431
 */
432
function return_gateway_groups_array() {
433
	global $config, $g;
434

    
435
	/* fetch the current gateways status */
436
	$gateways_status = return_gateways_status(true);
437
	$gateways_arr = return_gateways_array();
438
	$gateway_groups_array = array();
439

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

    
483
	if (is_array($config['gateways']['gateway_group'])) {
484
		foreach($config['gateways']['gateway_group'] as $group) {
485
			/* create array with group gateways members seperated by tier */
486
			$tiers = array();
487
			$backupplan = array();
488
			foreach($group['item'] as $item) {
489
				$itemsplit = explode("|", $item);
490
				$tier = $itemsplit[1];
491
				$gwname = $itemsplit[0];
492

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

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

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

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

    
583
function lookup_gateway_ip_by_name($name) {
584

    
585
	$gateways_arr = return_gateways_array();
586
        foreach ($gateways_arr as $gname => $gw) {
587
                if ($gw['name'] == $name || $gname == $name)
588
                        return $gw['gateway'];
589
        }
590

    
591
	return false;
592
}
593

    
594
function lookup_gateway_monitor_ip_by_name($name) {
595

    
596
        $gateways_arr = return_gateways_array();
597
	if (!empty($gateways_arr[$name])) {
598
		$gateway = $gateways_arr[$name];
599
		if(!is_ipaddr($gateway['monitor']))
600
			return $gateway['gateway'];
601

    
602
		return $gateway['monitor'];
603
        }
604

    
605
        return (false);
606
}
607

    
608
function lookup_gateway_interface_by_name($name) {
609

    
610
        $gateways_arr = return_gateways_array();
611
	if (!empty($gateways_arr[$name])) {
612
		$interfacegw = $gateway['interface'];
613
		return ($interfacegw);
614
        }
615

    
616
        return (false);
617
}
618

    
619
function get_interface_gateway($interface, &$dynamic = false) {
620
	global $config, $g;
621

    
622
	$gw = NULL;
623

    
624
	$gwcfg = $config['interfaces'][$interface];
625
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
626
		foreach($config['gateways']['gateway_item'] as $gateway) {
627
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
628
				$gw = $gateway['gateway'];
629
				break;
630
			}
631
		}
632
	}
633

    
634
	// for dynamic interfaces we handle them through the $interface_router file.
635
	if (!is_ipaddrv4($gw) && !is_ipaddrv4($gwcfg['ipaddr'])) {
636
		$realif = get_real_interface($interface);
637
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
638
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
639
			$dynamic = true;
640
		}
641
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
642
			$dynamic = "default";
643
			
644
	}
645

    
646
	/* return gateway */
647
	return ($gw);
648
}
649

    
650
function get_interface_gateway_v6($interface, &$dynamic = false) {
651
	global $config, $g;
652

    
653
	$gw = NULL;
654
	$gwcfg = $config['interfaces'][$interface];
655
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
656
		foreach($config['gateways']['gateway_item'] as $gateway) {
657
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
658
				$gw = $gateway['gateway'];
659
				break;
660
			}
661
		}
662
	}
663

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

    
679
/* Check a IP address against a gateway IP or name
680
 * to verify it's address family */
681
function validate_address_family($ipaddr, $gwname) {
682
	$v4ip = false;
683
	$v6ip = false;
684
	$v4gw = false;
685
	$v6gw = false;
686

    
687
	if(is_ipaddrv4($ipaddr))
688
		$v4ip = true;
689
	if(is_ipaddrv6($ipaddr))
690
		$v6ip = true;
691
	if(is_ipaddrv4($gwname))
692
		$v4gw = true;
693
	if(is_ipaddrv6($gwname))
694
		$v6gw = true;
695

    
696
	if($v4ip && $v4gw)
697
		return true;
698
	if($v6ip && $v6gw)
699
		return true;
700

    
701
	/* still no match, carry on, lookup gateways */
702
	if(is_ipaddrv4(lookup_gateway_ip_by_name($gwname)))
703
		$v4gw = true;
704
	if(is_ipaddrv6(lookup_gateway_ip_by_name($gwname)))
705
		$v6gw = true;
706
	/* are they dynamic */
707
	switch($gwname) {
708
		case "dynamic":
709
			$v4gw = true;
710
			break;
711
		case "dynamic6":
712
			$v6gw = true;
713
			break;
714
	}
715

    
716
	if($v4ip && $v4gw)
717
		return true;
718
	if($v6ip && $v6gw)
719
		return true;
720
	
721
	return false;
722
}
723

    
724

    
725
?>
(24-24/62)