Project

General

Profile

Download (22.5 KB) Statistics
| Branch: | Tag: | Revision:
1 17623ab5 Bill Marquette
<?php
2
/*
3 cdcea13f Seth Mos
  Copyright (C) 2008 Bill Marquette, Seth Mos
4 c1191d5b Ermal
  Copyright (C) 2010 Ermal Lu?i
5 17623ab5 Bill Marquette
  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 c1191d5b Ermal
  1. Redistributions of source code must retain the above copyright notice,
11 17623ab5 Bill Marquette
  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 523855b0 Scott Ullrich
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/sbin/route	/usr/local/sbin/apinger
29
	pfSense_MODULE:	routing
30
31 c1191d5b Ermal
 */
32 17623ab5 Bill Marquette
33 3d471a14 Ermal
/*
34
 * Creates monitoring configuration file and
35
 * adds apropriate static routes.
36 cdcea13f Seth Mos
 */
37
function setup_gateways_monitor() {
38 3d471a14 Ermal
	global $config, $g;
39 ffe76308 Seth Mos
40 3d471a14 Ermal
	$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 cdcea13f Seth Mos
48 3d471a14 Ermal
	/* Default settings. Probably should move to globals.inc? */
49 023920e7 Ermal
	$a_settings = array();
50
	$a_settings['latencylow'] = "200";
51
	$a_settings['latencyhigh'] = "500";
52
	$a_settings['losslow'] = "10";
53
	$a_settings['losshigh'] = "20";
54 37c98ef9 Seth Mos
55 cdcea13f Seth Mos
	$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 0534d60a Chris Buechler
user "root"
62
group "wheel"
63 cdcea13f Seth Mos
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 298e5e0a Ermal
	file "{$g['tmp_path']}/apinger.status"
76 cdcea13f Seth Mos
	## Interval between file updates
77
	## when 0 or not set, file is written only when SIGUSR1 is received
78 ecb08c6a Ermal
	interval 5s
79 cdcea13f Seth Mos
}
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 0ae6daf8 Ermal
	command on "/usr/local/sbin/pfSctl -c 'filter reload'"
89
	command off "/usr/local/sbin/pfSctl -c 'filter reload'"
90 cdcea13f Seth Mos
	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 37c98ef9 Seth Mos
	delay_low {$a_settings['latencylow']}ms
104
	delay_high {$a_settings['latencyhigh']}ms
105 cdcea13f Seth Mos
}
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 37c98ef9 Seth Mos
	percent_low {$a_settings['losslow']}
112
	percent_high {$a_settings['losshigh']}
113 cdcea13f Seth Mos
}
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 1bce2729 Seth Mos
	#rrd file "{$g['vardb_path']}/rrd/apinger-%t.rrd"
135 cdcea13f Seth Mos
}
136
137
EOD;
138
139 3d471a14 Ermal
	foreach($gateways_arr as $name => $gateway) {
140 33c06ef7 Ermal
		/* Do not monitor if such was requested */
141
		if (isset($gateway['monitor_disable']))
142
			continue;
143 3d471a14 Ermal
		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 f31ab121 Ermal
				continue;
148 3d471a14 Ermal
		}
149 f31ab121 Ermal
150 3d471a14 Ermal
		/* Interface ip is needed since apinger will bind a socket to it. */
151 640b3a9a Seth Mos
		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 3d471a14 Ermal
		if (!is_ipaddr($gwifip))
158
			continue; //Skip this target
159
160 f44f8eb5 Ermal
		$apingercfg = "target \"{$gateway['monitor']}\" {\n";
161 68f291ff Ermal
		$apingercfg .= "	description \"{$name}\"\n";
162 3d471a14 Ermal
		$apingercfg .= "	srcip \"{$gwifip}\"\n";
163 f7203985 Ermal
		if (!empty($gateway['interval']) && intval($gateway['interval']) > 1)
164
			$apingercfg .= "	interval " . intval($gateway['interval']) . "s\n";
165 3d471a14 Ermal
		$alarms = "";
166 f44f8eb5 Ermal
		$alarmscfg = "";
167 3d471a14 Ermal
		$override = false;
168
		if (!empty($gateway['lowloss'])) {
169 68f291ff Ermal
			$alarmscfg .= "alarm loss \"{$name}loss\" {\n";
170 3d471a14 Ermal
			$alarmscfg .= "\tpercent_low {$gateway['losslow']}\n";
171
       			$alarmscfg .= "\tpercent_high {$gateway['losshigh']}\n";
172
			$alarmscfg .= "}\n";
173 68f291ff Ermal
			$alarms .= "\"{$name}loss\"";
174 3d471a14 Ermal
			$override = true;
175
		} else {
176 023920e7 Ermal
			if ($override == true)
177 3d471a14 Ermal
				$alarms .= ",";
178
			$alarms .= "\"loss\"";
179
			$override = true;
180
		}
181
		if (!empty($gateway['latencylow'])) {
182 68f291ff Ermal
			$alarmscfg .= "alarm delay \"{$name}delay\" {\n";
183 3d471a14 Ermal
			$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 68f291ff Ermal
			$alarms .= "\"{$name}delay\"";
189 3d471a14 Ermal
			$override = true;
190
		} else {
191
			if ($override == true)
192
				$alarms .= ",";
193
			$alarms .= "\"delay\"";
194
			$override = true;
195
		}
196
		if (!empty($gateway['down'])) {
197 68f291ff Ermal
			$alarmscfg .= "alarm down \"{$name}down\" {\n";
198 3d471a14 Ermal
			$alarmscfg .= "\ttime {$gateway['down']}s\n";
199
			$alarmscfg .= "}\n";
200
			if ($override == true)
201
				$alarms .= ",";
202 68f291ff Ermal
			$alarms .= "\"{$name}down\"";
203 3d471a14 Ermal
			$override = true;
204
		} else {
205
			if ($override == true)
206
				$alarms .= ",";
207
			$alarms .= "\"down\"";
208
			$override = true;
209 cdcea13f Seth Mos
		}
210 3d471a14 Ermal
		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 b8452906 Vinicius Coque
			log_error(sprintf(gettext('Removing static route for monitor %1$s and adding a new route through %2$s'), $gateway['monitor'], $gateway['gateway']));
224 74dafdec Ermal
			mwexec("/sbin/route change -host " . escapeshellarg($gateway['monitor']) .
225 435a418f Ermal
				" " . escapeshellarg($gateway['gateway']), true);
226 3d471a14 Ermal
		}
227
228 023920e7 Ermal
		$apingerconfig .= $alarmscfg;
229
		$apingerconfig .= $apingercfg;
230 cdcea13f Seth Mos
	}
231
	fwrite($fd, $apingerconfig);
232
	fclose($fd);
233
234 20f26a50 Ermal
	killbypid("{$g['varrun_path']}/apinger.pid");
235
	if (is_dir("{$g['tmp_path']}"))
236
		chmod("{$g['tmp_path']}", 01777);
237 17649c87 Ermal
	if (!is_dir("{$g['vardb_path']}/rrd"))
238 21934843 jim-p
		mkdir("{$g['vardb_path']}/rrd", 0775);
239 17649c87 Ermal
240
	@chown("{$g['vardb_path']}/rrd", "nobody");
241
242 20f26a50 Ermal
	/* start a new apinger process */
243 298e5e0a Ermal
	@unlink("{$g['tmp_path']}/apinger.status");
244 9132ae35 Ermal
	sleep(1);
245 20f26a50 Ermal
	mwexec_bg("/usr/local/sbin/apinger -c {$g['varetc_path']}/apinger.conf");
246 4f060616 Ermal
247 cdcea13f Seth Mos
	return 0;
248
}
249
250
/* return the status of the apinger targets as a array */
251 3d471a14 Ermal
function return_gateways_status($byname = false) {
252 ae9618af Ermal
	global $config, $g;
253 cdcea13f Seth Mos
254
	$apingerstatus = array();
255 d9dda2a5 Ermal
	if (file_exists("{$g['tmp_path']}/apinger.status")) {
256 cdcea13f Seth Mos
		$apingerstatus = file("{$g['tmp_path']}/apinger.status");
257 2328dcc5 Seth Mos
	}
258 cdcea13f Seth Mos
259 67ee1ec5 Ermal Luçi
	$status = array();
260 cdcea13f Seth Mos
	foreach($apingerstatus as $line) {
261 75466131 Ermal
		$info = explode("|", $line);
262 3d471a14 Ermal
		if ($byname == false)
263
			$target = $info[0];
264
		else
265
			$target = $info[2];
266
		$status[$target]['monitorip'] = $info[0];
267 79b7f498 Ermal
		$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 cdcea13f Seth Mos
	}
274 68f291ff Ermal
275 cdcea13f Seth Mos
	return($status);
276 17623ab5 Bill Marquette
}
277
278 2328dcc5 Seth Mos
/* Return all configured gateways on the system */
279 c795339e Ermal Lu?i
function return_gateways_array($disabled = false) {
280 8d3556c2 gnhb
	global $config, $g;
281 7901dff5 Ermal Luçi
282 c66b4242 Seth Mos
	$gateways_arr = array();
283
284 01ba0a72 Ermal Lu?i
	$i = 0;
285 3d471a14 Ermal
	/* Process/add all the configured gateways. */
286 ef05ae5f Ermal
	if (is_array($config['gateways']['gateway_item'])) {
287 2328dcc5 Seth Mos
		foreach($config['gateways']['gateway_item'] as $gateway) {
288 78ae2b14 Ermal
			if(empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
289 2328dcc5 Seth Mos
				$gateway['gateway'] = get_interface_gateway($gateway['interface']);
290
				/* no IP address found, set to dynamic */
291 3d471a14 Ermal
				if(! is_ipaddr($gateway['gateway']))
292 2328dcc5 Seth Mos
					$gateway['gateway'] = "dynamic";
293 a2532739 Ermal Lu?i
				$gateway['dynamic'] = true;
294 2328dcc5 Seth Mos
			}
295 33c06ef7 Ermal
			if (isset($gateway['monitor_disable']))
296
				$gateway['monitor_disable'] = true;
297
			else if (empty($gateway['monitor']))
298 2328dcc5 Seth Mos
				$gateway['monitor'] = $gateway['gateway'];
299 3d471a14 Ermal
300 883c53c9 Ermal Lu?i
			$gateway['friendlyiface'] = $gateway['interface'];
301 3d471a14 Ermal
			$gateway['interface'] = get_real_interface($gateway['interface']);
302 979c816c Ermal
			/* FIXME: Should this be enabled.
303
			 * Some interface like wan might be default but have no info recorded 
304 bb8f919b Ermal
			 * the config.
305
			if ($gateway['friendlyiface'] == "wan" && !isset($gateway['defaultgw'])) {
306
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw"))
307
					$gateway['defaultgw'] = true;
308
			}
309 979c816c Ermal
			 */
310 3d471a14 Ermal
			/* include the gateway index as the attribute */
311
			$gateway['attribute'] = $i;
312 2328dcc5 Seth Mos
313
			$gateways_arr[$gateway['name']] = $gateway;
314
			$i++;
315
		}
316 883c53c9 Ermal Lu?i
	} 
317
318 ef05ae5f Ermal
	/* Loop through all interfaces with a gateway and add it to a array */
319
	if ($disabled == false)
320
		$iflist = get_configured_interface_with_descr();
321
	else
322
		$iflist = get_configured_interface_with_descr(false, true);
323
324 c3a0d2a5 Seth Mos
	/* Process/add dynamic v4 gateways. */
325 883c53c9 Ermal Lu?i
	foreach($iflist as $ifname => $friendly ) {
326 3d471a14 Ermal
		if(! interface_has_gateway($ifname))
327 883c53c9 Ermal Lu?i
			continue;
328 3d471a14 Ermal
329 86df2846 jim-p
		if (empty($config['interfaces'][$ifname]))
330
			continue;
331
332
		$ifcfg = &$config['interfaces'][$ifname];
333 c3a0d2a5 Seth Mos
		if(!empty($ifcfg['ipaddr']) && is_ipaddrv4($ifcfg['ipaddr']))
334 e62fe748 Ermal
			continue;
335
336 883c53c9 Ermal Lu?i
		$gateway = array();
337
		$gateway['dynamic'] = false;
338 c3a0d2a5 Seth Mos
		$gateway['ipprotocol'] = "inet";
339 883c53c9 Ermal Lu?i
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
340
		$gateway['interface'] = get_real_interface($ifname);
341
		$gateway['friendlyiface'] = $ifname;
342 ef05ae5f Ermal
		$gateway['name'] = $friendly;
343 883c53c9 Ermal Lu?i
		$gateway['attribute'] = "system";
344 2328dcc5 Seth Mos
	
345 6adc8e32 gnhb
		if ($gateway['dynamic'] === "default") {
346 999111cb Ermal
			$gateway['defaultgw'] = true;
347
			$gateway['dynamic'] = true;
348
		}
349 883c53c9 Ermal Lu?i
		/* Loopback dummy for dynamic interfaces without a IP */
350 c3a0d2a5 Seth Mos
		if (!is_ipaddrv4($gateway['gateway']) && $gateway['dynamic'] == true)
351 999111cb Ermal
			$gateway['gateway'] = "dynamic";
352 3439b033 Seth Mos
353 883c53c9 Ermal Lu?i
		/* automatically skip known static and dynamic gateways we have a array entry for */
354
		foreach($gateways_arr as $gateway_item) {
355 c3a0d2a5 Seth Mos
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name'])&& ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
356
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
357 7bed8222 Ermal
					continue 2;
358 883c53c9 Ermal Lu?i
		}
359 c66b4242 Seth Mos
360 c3a0d2a5 Seth Mos
		if (is_ipaddrv4($gateway['gateway']))
361 883c53c9 Ermal Lu?i
			$gateway['monitor'] = $gateway['gateway'];
362 c65e1e0d Ermal
363
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
364 c3a0d2a5 Seth Mos
		$gateways_arr[$gateway['name']] = $gateway;
365
	}
366
367
	/* Process/add dynamic v6 gateways. */
368
	foreach($iflist as $ifname => $friendly ) {
369
		if(! interface_has_gateway($ifname))
370
			continue;
371
372
		if (empty($config['interfaces'][$ifname]))
373
			continue;
374
375
		$ifcfg = &$config['interfaces'][$ifname];
376
		if(!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
377
			continue;
378
379
		$gateway = array();
380
		$gateway['dynamic'] = false;
381
		$gateway['ipprotocol'] = "inet6";
382
		$gateway['gateway'] = get_interface_gateway_v6($ifname, $gateway['dynamic']);
383
		$gateway['interface'] = get_real_interface($ifname);
384
		$gateway['friendlyiface'] = $ifname;
385
		$gateway['name'] = "{$friendly}_v6";
386
		$gateway['attribute'] = "system";
387
	
388
		if ($gateway['dynamic'] === "default") {
389
			$gateway['defaultgw'] = true;
390
			$gateway['dynamic'] = true;
391
		}
392
393
		/* Loopback dummy for dynamic interfaces without a IP */
394
		if (!is_ipaddrv6($gateway['gateway']) && $gateway['dynamic'] == true)
395
			$gateway['gateway'] = "dynamic";
396
397
		/* automatically skip known static and dynamic gateways we have a array entry for */
398
		foreach($gateways_arr as $gateway_item) {
399
			if ((($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol'])) ||
400
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true) && ($gateway['ipprotocol'] == $gateway_item['ipprotocol']))
401
					continue 2;
402
		}
403
404
		if (is_ipaddrv6($gateway['gateway']))
405
			$gateway['monitor'] = $gateway['gateway'];
406
407
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
408
		$gateways_arr[$gateway['name']] = $gateway;
409 c66b4242 Seth Mos
	}
410 883c53c9 Ermal Lu?i
411 c66b4242 Seth Mos
	return($gateways_arr);
412
}
413
414 3d471a14 Ermal
/*
415
 * Return an array with all gateway groups with name as key
416 fd8eeda5 Seth Mos
 * All gateway groups will be processed before returning the array.
417 3d471a14 Ermal
 */
418 fd8eeda5 Seth Mos
function return_gateway_groups_array() {
419 962625aa Ermal
	global $config, $g;
420 fd8eeda5 Seth Mos
421
	/* fetch the current gateways status */
422 3d471a14 Ermal
	$gateways_status = return_gateways_status(true);
423 fd8eeda5 Seth Mos
	$gateways_arr = return_gateways_array();
424
	$gateway_groups_array = array();
425
426 7af360ce Ermal
	if (isset($config['system']['gw_switch_default'])) {
427 e75be7fc Ermal
		/* 
428
		 * NOTE: The code below is meant to replace the default gateway when it goes down.
429
		 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
430
		 */
431
		$upgw = "";
432
		$dfltgwdown = false;
433
		$dfltgwfound = false;
434
		foreach ($gateways_arr as $gwname => $gwsttng) {
435
			if (isset($gwsttng['defaultgw'])) {
436
				$dfltgwfound = true;
437
				$dfltgwname = $gwname;
438 33c06ef7 Ermal
				if (!isset($gwsttng['monitor_disable']) && stristr($gateways_status[$gwname]['status'], "down"))
439 e75be7fc Ermal
					$dfltgwdown = true;
440
			}
441
			/* Keep a record of the last up gateway */
442 e56a7306 Ermal
			/* XXX: Blacklist lan for now since it might cause issues to those who have a gateway set for it */
443 e9df45f0 Ermal
			if (empty($upgw) && (isset($gwsttng['monitor_disable']) || !stristr($gateways_status[$gwname]['status'], "down")) && $gwsttng[$gwname]['friendlyiface'] != "lan")
444 e75be7fc Ermal
				$upgw = $gwname;
445
			if ($dfltgwdown == true && !empty($upgw))
446
				break;
447
		}
448
		if ($dfltgwfound == false) {
449
			$gwname = convert_friendly_interface_to_friendly_descr("wan");
450 33c06ef7 Ermal
			if (!empty($gateways_status[$gwname]) && stristr($gateways_status[$gwname]['status'], "down"))
451 19d91466 Ermal
				$dfltgwdown = true;
452
		}
453 e75be7fc Ermal
		if ($dfltgwdown == true && !empty($upgw)) {
454
			if ($gateways_arr[$upgw]['gateway'] == "dynamic")
455
				$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
456
			if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
457
				log_error("Default gateway down setting {$upgw} as default!");
458 74dafdec Ermal
				mwexec("/sbin/route change -inet default {$gateways_arr[$upgw]['gateway']}");
459 e75be7fc Ermal
			}
460
		} else {
461
			$defaultgw = trim(`/sbin/route -n get -inet default | /usr/bin/grep gateway | /usr/bin/sed 's/gateway://g'`, " \n");
462
			if ($defaultgw != $gateways_arr[$dfltgwname]['gateway'])
463 74dafdec Ermal
				mwexec("/sbin/route change -inet default {$gateways_arr[$dfltgwname]['gateway']}");
464 1d60ed9b Ermal
		}
465 e75be7fc Ermal
				
466
		unset($upgw, $dfltgwfound, $dfltgwdown, $gwname, $gwsttng);
467 ee7f1647 Ermal
	}
468 1d60ed9b Ermal
469 fd8eeda5 Seth Mos
	if (is_array($config['gateways']['gateway_group'])) {
470
		foreach($config['gateways']['gateway_group'] as $group) {
471
			/* create array with group gateways members seperated by tier */
472
			$tiers = array();
473 3d471a14 Ermal
			$backupplan = array();
474 fd8eeda5 Seth Mos
			foreach($group['item'] as $item) {
475
				$itemsplit = explode("|", $item);
476
				$tier = $itemsplit[1];
477
				$gwname = $itemsplit[0];
478 3d471a14 Ermal
479
				/* Do it here rather than reiterating again the group in case no member is up. */
480 d8bf779b Ermal
				$backupplan[$tier][] = $gwname;
481 3d471a14 Ermal
482 fd8eeda5 Seth Mos
				/* check if the gateway is available before adding it to the array */
483 54b78cc1 Ermal
				if (!empty($gateways_status[$gwname])) {
484
					$status = $gateways_status[$gwname];
485 3d471a14 Ermal
					$gwdown = false;
486 9af4b31b Ermal
					if (stristr($status['status'], "down")) {
487 a51493d1 Vinicius Coque
						$msg = sprintf(gettext("MONITOR: %s is down, removing from routing group"), $gwname);
488 3d471a14 Ermal
						$gwdown = true;
489
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
490
						/* packet loss */
491 f14bd707 Renato Botelho
						$msg = sprintf(gettext("MONITOR: %s has packet loss, removing from routing group"), $gwname);
492 3d471a14 Ermal
						$gwdown = true;
493
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
494
						/* high latency */
495 f14bd707 Renato Botelho
						$msg = sprintf(gettext("MONITOR: %s has high latency, removing from routing group"), $gwname);
496 3d471a14 Ermal
						$gwdown = true;
497
					}
498
					if ($gwdown == true) {
499 9f1d61d3 Scott Ullrich
						log_error($msg);
500
						notify_via_growl($msg);
501 10c3d4c0 Scott Ullrich
						notify_via_smtp($msg);
502 3d471a14 Ermal
					} else
503 857ce5f3 Seth Mos
						/* Online add member */
504
						$tiers[$tier][] = $gwname;
505 33c06ef7 Ermal
				} else if (isset($gateways_arr[$gwname]['monitor_disable']))
506
					$tiers[$tier][] = $gwname;
507 fd8eeda5 Seth Mos
			}
508
			$tiers_count = count($tiers);
509
			if($tiers_count == 0) {
510
				/* Oh dear, we have no members! Engage Plan B */
511 9132ae35 Ermal
				if (!$g['booting']) {
512 c92ccac7 Vinicius Coque
					$msg = gettext("Gateways status could not be determined, considering all as up/active.");
513 9132ae35 Ermal
					log_error($msg);
514
					notify_via_growl($msg);
515 10c3d4c0 Scott Ullrich
					notify_via_smtp($msg);
516 9132ae35 Ermal
				}
517 3d471a14 Ermal
				$tiers = $backupplan;
518 fd8eeda5 Seth Mos
			}
519 09ae0c17 Seth Mos
			/* sort the tiers array by the tier key */
520
			ksort($tiers);
521 3d471a14 Ermal
522 fd8eeda5 Seth Mos
			/* we do not really foreach the tiers as we stop after the first tier */
523 fe22a89b Ermal
			foreach($tiers as $tier) {
524 fd8eeda5 Seth Mos
				/* process all gateways in this tier */
525 fe22a89b Ermal
				foreach($tier as $member) {
526 fd8eeda5 Seth Mos
					/* determine interface gateway */
527 5f53260a Ermal
					if (isset($gateways_arr[$member])) {
528
						$gateway = $gateways_arr[$member];
529
						$int = $gateway['interface'];
530
						$gatewayip = "";
531
						if(is_ipaddr($gateway['gateway'])) 
532
							$gatewayip = $gateway['gateway'];
533
						else if ($int <> "")
534
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
535 3d471a14 Ermal
					
536
						if (($int <> "") && is_ipaddr($gatewayip)) {
537
							$groupmember = array();
538
							$groupmember['int']  = $int;
539
							$groupmember['gwip']  = $gatewayip;
540
							$groupmember['weight']  = isset($gateway['weight']) ? $gateway['weight'] : 1;
541
							$gateway_groups_array[$group['name']][] = $groupmember;
542
						}
543 fd8eeda5 Seth Mos
					}
544
				}
545
				/* we should have the 1st available tier now, exit stage left */
546
				break;
547
			}
548
		}
549
	}
550 fe22a89b Ermal
	return ($gateway_groups_array);
551 fd8eeda5 Seth Mos
}
552
553 2468ae76 Scott Ullrich
/* Update DHCP WAN Interface ip address in gateway group item */
554
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
555
	global $config, $g;
556
	foreach($config['gateways']['gateway_item'] as & $gw) {	
557
		if($gw['interface'] == $interface) {
558
			$current_gw = get_interface_gateway($interface);
559
			if($gw['gateway'] <> $current_gw) {
560
				$gw['gateway'] = $current_gw;
561
				$changed = true;
562
			}
563
		}
564
	}
565
	if($changed && $current_gw)
566 addc0439 Renato Botelho
		write_config(sprintf(gettext('Updating gateway group gateway for %1$s - new gateway is %2$s'), $interfac, $current_gw));
567 2468ae76 Scott Ullrich
}
568 fd8eeda5 Seth Mos
569 6dc3a5c2 Ermal Lu?i
function lookup_gateway_ip_by_name($name) {
570 fe22a89b Ermal
571 66a96e72 Ermal
	$gateways_arr = return_gateways_array();
572 68f291ff Ermal
        foreach ($gateways_arr as $gname => $gw) {
573
                if ($gw['name'] == $name || $gname == $name)
574 6f77aca5 Ermal
                        return $gw['gateway'];
575
        }
576 66a96e72 Ermal
577
	return false;
578 6dc3a5c2 Ermal Lu?i
}
579
580
function lookup_gateway_monitor_ip_by_name($name) {
581 fe22a89b Ermal
582 6dc3a5c2 Ermal Lu?i
        $gateways_arr = return_gateways_array();
583 fe22a89b Ermal
	if (!empty($gateways_arr[$name])) {
584
		$gateway = $gateways_arr[$name];
585 68f291ff Ermal
		if(!is_ipaddr($gateway['monitor']))
586
			return $gateway['gateway'];
587 6dc3a5c2 Ermal Lu?i
588 9fd19334 gnhb
		return $gateway['monitor'];
589 6dc3a5c2 Ermal Lu?i
        }
590 fe22a89b Ermal
591
        return (false);
592 6dc3a5c2 Ermal Lu?i
}
593
594
function lookup_gateway_interface_by_name($name) {
595
596 fe22a89b Ermal
        $gateways_arr = return_gateways_array();
597
	if (!empty($gateways_arr[$name])) {
598
		$interfacegw = $gateway['interface'];
599
		return ($interfacegw);
600 6dc3a5c2 Ermal Lu?i
        }
601 fe22a89b Ermal
602
        return (false);
603 6dc3a5c2 Ermal Lu?i
}
604
605 a2532739 Ermal Lu?i
function get_interface_gateway($interface, &$dynamic = false) {
606 5a5413bb Seth Mos
	global $config, $g;
607 6dc3a5c2 Ermal Lu?i
608 5a5413bb Seth Mos
	$gw = NULL;
609 6dc3a5c2 Ermal Lu?i
610 5a5413bb Seth Mos
	$gwcfg = $config['interfaces'][$interface];
611
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
612
		foreach($config['gateways']['gateway_item'] as $gateway) {
613
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
614
				$gw = $gateway['gateway'];
615 66a96e72 Ermal
				break;
616
			}
617 5a5413bb Seth Mos
		}
618 66a96e72 Ermal
	}
619 6dc3a5c2 Ermal Lu?i
620 5a5413bb Seth Mos
	// for dynamic interfaces we handle them through the $interface_router file.
621
	if (!is_ipaddr($gw) && !is_ipaddr($gwcfg['ipaddr'])) {
622
		$realif = get_real_interface($interface);
623
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
624
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
625
			$dynamic = true;
626
		}
627
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
628
			$dynamic = "default";
629 d62b164a gnhb
			
630 5a5413bb Seth Mos
	}
631
632
	/* return gateway */
633
	return ($gw);
634
}
635
636
function get_interface_gateway_v6($interface, &$dynamic = false) {
637
	global $config, $g;
638 6dc3a5c2 Ermal Lu?i
639 5a5413bb Seth Mos
	$gw = NULL;
640
	$gwcfg = $config['interfaces'][$interface];
641 ed5c640d Seth Mos
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
642 5a5413bb Seth Mos
		foreach($config['gateways']['gateway_item'] as $gateway) {
643 640b3a9a Seth Mos
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
644 5a5413bb Seth Mos
				$gw = $gateway['gateway'];
645
				break;
646
			}
647
		}
648
	}
649
650
	// for dynamic interfaces we handle them through the $interface_router file.
651
	if (!is_ipaddrv6($gw) && !is_ipaddr($gwcfg['ipaddrv6'])) {
652
			$realif = get_real_interface($interface);
653
			if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
654
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
655
				$dynamic = true;
656
			}
657
			if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6"))
658
				$dynamic = "default";
659
			
660
	}
661
	/* return gateway */
662
	return ($gw);
663 6dc3a5c2 Ermal Lu?i
}
664
665 318189b6 smos
/* Check a IP address against a gateway IP or name
666
 * to verify it's address family */
667
function validate_address_family($ipaddr, $gwname) {
668
	$v4ip = false;
669
	$v6ip = false;
670
	$v4gw = false;
671
	$v6gw = false;
672
673
	if(is_ipaddrv4($ipaddr))
674
		$v4ip = true;
675
	if(is_ipaddrv6($ipaddr))
676
		$v6ip = true;
677
	if(is_ipaddrv4($gwname))
678
		$v4gw = true;
679
	if(is_ipaddrv6($gwname))
680
		$v6gw = true;
681
682
	if($v4ip && $v4gw)
683
		return true;
684
	if($v6ip && $v6gw)
685
		return true;
686
687
	/* still no match, carry on, lookup gateways */
688
	if(is_ipaddrv4(lookup_gateway_ip_by_name($gwname)))
689
		$v4gw = true;
690
	if(is_ipaddrv6(lookup_gateway_ip_by_name($gwname)))
691
		$v6gw = true;
692
693
	if($v4ip && $v4gw)
694
		return true;
695
	if($v6ip && $v6gw)
696
		return true;
697
	
698
	return false;
699
}
700
701
702 315e1253 Ermal
?>