Project

General

Profile

Download (40 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	rrd.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (C) 2010 Seth Mos <seth.mos@dds.nl>
7
	Copyright (c) 2010-2016 Electric Sheep Fencing, LLC.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

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

    
21
	3. All advertising materials mentioning features or use of this software
22
	   must display the following acknowledgment:
23
	   "This product includes software developed by the pfSense Project
24
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
25

    
26
	4. The names "pfSense" and "pfSense Project" must not be used to
27
	   endorse or promote products derived from this software without
28
	   prior written permission. For written permission, please contact
29
	   coreteam@pfsense.org.
30

    
31
	5. Products derived from this software may not be called "pfSense"
32
	   nor may "pfSense" appear in their names without prior written
33
	   permission of the Electric Sheep Fencing, LLC.
34

    
35
	6. Redistributions of any form whatsoever must retain the following
36
	   acknowledgment:
37

    
38
	"This product includes software developed by the pfSense Project
39
	for use in the pfSense software distribution (http://www.pfsense.org/).
40

    
41
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
42
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
45
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
	OF THE POSSIBILITY OF SUCH DAMAGE.
53
*/
54

    
55
/* include all configuration functions */
56

    
57
function dump_rrd_to_xml($rrddatabase, $xmldumpfile) {
58
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
59
	unlink_if_exists($xmldumpfile);
60

    
61
	exec("$rrdtool dump " . escapeshellarg($rrddatabase) . " {$xmldumpfile} 2>&1", $dumpout, $dumpret);
62
	if ($dumpret <> 0) {
63
		$dumpout = implode(" ", $dumpout);
64
		log_error(sprintf(gettext('RRD dump failed exited with %1$s, the error is: %2$s'), $dumpret, $dumpout));
65
	}
66
	return($dumpret);
67
}
68

    
69
function restore_rrd() {
70
	global $g, $config;
71

    
72
	$rrddbpath = "{$g['vardb_path']}/rrd/";
73
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
74

    
75
	$rrdrestore = "";
76
	$rrdreturn = "";
77
	if (file_exists("{$g['cf_conf_path']}/rrd.tgz") && (isset($config['system']['use_mfs_tmpvar']) || $g['platform'] != $g['product_name'])) {
78
		foreach (glob("{$rrddbpath}/*.xml") as $xml_file) {
79
			@unlink($xml_file);
80
		}
81
		unset($rrdrestore);
82
		$_gb = exec("cd /;LANG=C /usr/bin/tar -tf {$g['cf_conf_path']}/rrd.tgz", $rrdrestore, $rrdreturn);
83
		if ($rrdreturn != 0) {
84
			log_error(sprintf(gettext('RRD restore failed exited with %1$s, the error is: %2$s'), $rrdreturn, $rrdrestore));
85
			return;
86
		}
87
		foreach ($rrdrestore as $xml_file) {
88
			$rrd_file = '/' . substr($xml_file, 0, -4) . '.rrd';
89
			if (file_exists("{$rrd_file}")) {
90
				@unlink($rrd_file);
91
			}
92
			file_put_contents("{$g['tmp_path']}/rrd_restore", $xml_file);
93
			$_gb = exec("cd /;LANG=C /usr/bin/tar -xf {$g['cf_conf_path']}/rrd.tgz -T {$g['tmp_path']}/rrd_restore");
94
			if (!file_exists("/{$xml_file}")) {
95
				log_error(sprintf(gettext("Could not extract %s RRD xml file from archive!"), $xml_file));
96
				continue;
97
			}
98
			$_gb = exec("$rrdtool restore -f '/{$xml_file}' '{$rrd_file}'", $output, $status);
99
			if ($status) {
100
				log_error(sprintf(gettext("rrdtool restore -f '%1\$s' '%2\$s' failed returning %3\$s."), $xml_file, $rrd_file, $status));
101
				continue;
102
			}
103
			unset($output);
104
			@unlink("/{$xml_file}");
105
		}
106
		unset($rrdrestore);
107
		@unlink("{$g['tmp_path']}/rrd_restore");
108
		/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
109
		if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
110
			unlink_if_exists("{$g['cf_conf_path']}/rrd.tgz");
111
		}
112
		return true;
113
	}
114
	return false;
115
}
116

    
117
function create_new_rrd($rrdcreatecmd) {
118
	$rrdcreateoutput = array();
119
	$rrdcreatereturn = 0;
120
	$_gb = exec("$rrdcreatecmd 2>&1", $rrdcreateoutput, $rrdcreatereturn);
121
	if ($rrdcreatereturn <> 0) {
122
		$rrdcreateoutput = implode(" ", $rrdcreateoutput);
123
		log_error(sprintf(gettext('RRD create failed exited with %1$s, the error is: %2$s'), $rrdcreatereturn, $rrdcreateoutput));
124
	}
125
	unset($rrdcreateoutput);
126
	return $rrdcreatereturn;
127
}
128

    
129
function migrate_rrd_format($rrdoldxml, $rrdnewxml) {
130
	if (!file_exists("/tmp/rrd_notice_sent.txt")) {
131
		$_gb = exec("echo 'Converting RRD configuration to new format.  This might take a bit...' | wall");
132
		@touch("/tmp/rrd_notice_sent.txt");
133
	}
134
	$numrraold = count($rrdoldxml['rra']);
135
	$numrranew = count($rrdnewxml['rra']);
136
	$numdsold = count($rrdoldxml['ds']);
137
	$numdsnew = count($rrdnewxml['ds']);
138
	log_error(sprintf(gettext('Import RRD has %1$s DS values and %2$s RRA databases, new format RRD has %3$s DS values and %4$s RRA databases'), $numdsold, $numrraold, $numdsnew , $numrranew));
139

    
140
	/* add data sources not found in the old array from the new array */
141
	$i = 0;
142
	foreach ($rrdnewxml['ds'] as $ds) {
143
		if (!is_array($rrdoldxml['ds'][$i])) {
144
			$rrdoldxml['ds'][$i] = $rrdnewxml['ds'][$i];
145
			/* set unknown values to 0 */
146
			$rrdoldxml['ds'][$i]['last_ds'] = " 0.0000000000e+00 ";
147
			$rrdoldxml['ds'][$i]['value'] = " 0.0000000000e+00 ";
148
			$rrdoldxml['ds'][$i]['unknown_sec'] = "0";
149
		}
150
		$i++;
151
	}
152

    
153
	$i = 0;
154
	$rracountold = count($rrdoldxml['rra']);
155
	$rracountnew = count($rrdnewxml['rra']);
156
	/* process each RRA, which contain a database */
157
	foreach ($rrdnewxml['rra'] as $rra) {
158
		if (!is_array($rrdoldxml['rra'][$i])) {
159
			$rrdoldxml['rra'][$i] = $rrdnewxml['rra'][$i];
160
		}
161

    
162
		$d = 0;
163
		/* process cdp_prep */
164
		$cdp_prep = $rra['cdp_prep'];
165
		foreach ($cdp_prep['ds'] as $ds) {
166
			if (!is_array($rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d])) {
167
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d] = $rrdnewxml['rra'][$i]['cdp_prep']['ds'][$d];
168
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['primary_value'] = " 0.0000000000e+00 ";
169
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['secondary_value'] = " 0.0000000000e+00 ";
170
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['value'] = " 0.0000000000e+00 ";
171
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['unknown_datapoints'] = "0";
172
			}
173
			$d++;
174
		}
175

    
176
		/* process database */
177
		$rows = $rra['database'];
178
		$k = 0;
179
		$rowcountold = count($rrdoldxml['rra'][$i]['database']['row']);
180
		$rowcountnew = count($rrdnewxml['rra'][$i]['database']['row']);
181
		$rowcountdiff = $rowcountnew - $rowcountold;
182
		/* save old rows for a bit before we put the required empty rows before it */
183
		$rowsdata = $rows;
184
		$rowsempty = array();
185
		$r = 0;
186
		while ($r < $rowcountdiff) {
187
			$rowsempty[] = $rrdnewxml['rra'][$i]['database']['row'][$r];
188
			$r++;
189
		}
190
		$rows = $rowsempty + $rowsdata;
191
		/* now foreach the rows in the database */
192
		foreach ($rows['row'] as $row) {
193
			if (!is_array($rrdoldxml['rra'][$i]['database']['row'][$k])) {
194
				$rrdoldxml['rra'][$i]['database']['row'][$k] = $rrdnewxml['rra'][$i]['database']['row'][$k];
195
			}
196
			$m = 0;
197
			$vcountold = count($rrdoldxml['rra'][$i]['database']['row'][$k]['v']);
198
			$vcountnew = count($rrdnewxml['rra'][$i]['database']['row'][$k]['v']);
199
			foreach ($row['v'] as $value) {
200
				if (empty($rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m])) {
201
					if (isset($valid)) {
202
						$rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m] = "0.0000000000e+00 ";
203
					} else {
204
						$rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m] = $rrdnewxml['rra'][$i]['database']['row'][$k]['v'][$m];
205
					}
206
				} else {
207
					if ($value <> " NaN ") {
208
						$valid = true;
209
					} else {
210
						$valid = false;
211
					}
212
				}
213
				$m++;
214
			}
215
			$k++;
216
		}
217
		$i++;
218
	}
219

    
220
	$numrranew = count($rrdoldxml['rra']);
221
	$numdsnew = count($rrdoldxml['ds']);
222
	log_error(sprintf(gettext('The new RRD now has %1$s DS values and %2$s RRA databases'), $numdsnew, $numrranew));
223
	return $rrdoldxml;
224
}
225

    
226
function enable_rrd_graphing() {
227
	global $config, $g, $altq_list_queues;
228

    
229
	if (platform_booting()) {
230
		echo gettext("Generating RRD graphs...");
231
	}
232

    
233
	$rrddbpath = "{$g['vardb_path']}/rrd/";
234
	$rrdgraphpath = "/usr/local/www/rrd";
235

    
236
	$traffic = "-traffic.rrd";
237
	$packets = "-packets.rrd";
238
	$states = "-states.rrd";
239
	$wireless = "-wireless.rrd";
240
	$queues = "-queues.rrd";
241
	$queuesdrop = "-queuedrops.rrd";
242
	$spamd = "-spamd.rrd";
243
	$proc = "-processor.rrd";
244
	$mem = "-memory.rrd";
245
	$mbuf = "-mbuf.rrd";
246
	$cellular = "-cellular.rrd";
247
	$vpnusers = "-vpnusers.rrd";
248
	$captiveportalconcurrent = "-concurrent.rrd";
249
	$captiveportalloggedin = "-loggedin.rrd";
250
	$ntpd = "ntpd.rrd";
251
	$dhcpd = "-dhcpd.rrd";
252

    
253
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
254
	$netstat = "/usr/bin/netstat";
255
	$awk = "/usr/bin/awk";
256
	$tar = "/usr/bin/tar";
257
	$pfctl = "/sbin/pfctl";
258
	$sysctl = "/sbin/sysctl";
259
	$php = "/usr/local/bin/php-cgi";
260
	$cpustats = "/usr/local/sbin/cpustats";
261
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
262
	$ifconfig = "/sbin/ifconfig";
263
	$captiveportal_gather = "/usr/local/bin/captiveportal_gather_stats.php";
264
	$dhcpd_gather = "/usr/local/bin/dhcpd_gather_stats.php";
265
	$ntpq = "/usr/local/sbin/ntpq";
266

    
267
	$rrdtrafficinterval = 60;
268
	$rrdwirelessinterval = 60;
269
	$rrdqueuesinterval = 60;
270
	$rrdqueuesdropinterval = 60;
271
	$rrdpacketsinterval = 60;
272
	$rrdstatesinterval = 60;
273
	$rrdspamdinterval = 60;
274
	$rrdlbpoolinterval = 60;
275
	$rrdprocinterval = 60;
276
	$rrdmeminterval = 60;
277
	$rrdmbufinterval = 60;
278
	$rrdcellularinterval = 60;
279
	$rrdvpninterval = 60;
280
	$rrdcaptiveportalinterval = 60;
281
	$rrdntpdinterval = 60;
282
	$rrddhcpdinterval = 60;
283

    
284
	$trafficvalid = $rrdtrafficinterval * 2;
285
	$wirelessvalid = $rrdwirelessinterval * 2;
286
	$queuesvalid = $rrdqueuesinterval * 2;
287
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
288
	$packetsvalid = $rrdpacketsinterval * 2;
289
	$statesvalid = $rrdstatesinterval*2;
290
	$spamdvalid = $rrdspamdinterval * 2;
291
	$lbpoolvalid = $rrdlbpoolinterval * 2;
292
	$procvalid = $rrdlbpoolinterval * 2;
293
	$memvalid = $rrdmeminterval * 2;
294
	$mbufvalid = $rrdmbufinterval * 2;
295
	$cellularvalid = $rrdcellularinterval * 2;
296
	$vpnvalid = $rrdvpninterval * 2;
297
	$captiveportalvalid = $rrdcaptiveportalinterval * 2;
298
	$ntpdvalid = $rrdntpdinterval * 2;
299
	$dhcpdvalid = $rrddhcpdinterval * 2;
300

    
301
	/* Assume 2*10GigE for now */
302
	$downstream = 2500000000;
303
	$upstream = 2500000000;
304

    
305
	/* read the shaper config */
306
	read_altq_config();
307

    
308
	if (isset ($config['rrd']['enable'])) {
309

    
310
		/* create directory if needed */
311
		if (!is_dir($rrddbpath)) {
312
			mkdir($rrddbpath, 0775);
313
		}
314
		chown($rrddbpath, "nobody");
315

    
316
		if (platform_booting()) {
317
			restore_rrd();
318
		}
319

    
320
		/* db update script */
321
		$rrdupdatesh = "#!/bin/sh\n";
322
		$rrdupdatesh .= "\n";
323
		$rrdupdatesh .= "export TERM=dumb\n";
324
		$rrdupdatesh .= "\n";
325
		$rrdupdatesh .= 'echo $$ > ' . $g['varrun_path'] . '/updaterrd.sh.pid';
326
		$rrdupdatesh .= "\n";
327
		$rrdupdatesh .= "counter=1\n";
328
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
329
		$rrdupdatesh .= "do\n";
330
		$rrdupdatesh .= "";
331

    
332
		$i = 0;
333
		$ifdescrs = get_configured_interface_with_descr();
334
		/* IPsec counters */
335
		$ifdescrs['ipsec'] = "IPsec";
336
		/* OpenVPN server counters */
337
		if (is_array($config['openvpn']['openvpn-server'])) {
338
			foreach ($config['openvpn']['openvpn-server'] as $server) {
339
				$serverid = "ovpns" . $server['vpnid'];
340
				$ifdescrs[$serverid] = "{$server['description']}";
341
			}
342
		}
343

    
344
		if (platform_booting()) {
345
			if (!is_dir($rrddbpath)) {
346
				mkdir($rrddbpath, 0775);
347
			}
348

    
349
			@chown($rrddbpath, "nobody");
350
		}
351

    
352
		/* process all real and pseudo interfaces */
353
		foreach ($ifdescrs as $ifname => $ifdescr) {
354
			$temp = get_real_interface($ifname);
355
			if ($temp <> "") {
356
				$realif = $temp;
357
			}
358

    
359
			/* TRAFFIC, set up the rrd file */
360
			if (!file_exists("$rrddbpath$ifname$traffic")) {
361
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
362
				$rrdcreate .= "DS:inpass:COUNTER:$trafficvalid:0:$downstream ";
363
				$rrdcreate .= "DS:outpass:COUNTER:$trafficvalid:0:$upstream ";
364
				$rrdcreate .= "DS:inblock:COUNTER:$trafficvalid:0:$downstream ";
365
				$rrdcreate .= "DS:outblock:COUNTER:$trafficvalid:0:$upstream ";
366
				$rrdcreate .= "DS:inpass6:COUNTER:$trafficvalid:0:$downstream ";
367
				$rrdcreate .= "DS:outpass6:COUNTER:$trafficvalid:0:$upstream ";
368
				$rrdcreate .= "DS:inblock6:COUNTER:$trafficvalid:0:$downstream ";
369
				$rrdcreate .= "DS:outblock6:COUNTER:$trafficvalid:0:$upstream ";
370
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
371
				$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
372
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
373
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
374

    
375
				create_new_rrd($rrdcreate);
376
				unset($rrdcreate);
377
			}
378

    
379
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
380
			if (platform_booting()) {
381
				mwexec("$rrdtool update $rrddbpath$ifname$traffic N:U:U:U:U:U:U:U:U");
382
			}
383

    
384
			$rrdupdatesh .= "\n";
385
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif IPv4/IPv6 counters \n";
386
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:";
387
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '\\\n";
388
			$rrdupdatesh .= "/In4\/Pass/ { b4pi = \$6 };/Out4\/Pass/ { b4po = \$6 };/In4\/Block/ { b4bi = \$6 };/Out4\/Block/ { b4bo = \$6 };\\\n";
389
			$rrdupdatesh .= "/In6\/Pass/ { b6pi = \$6 };/Out6\/Pass/ { b6po = \$6 };/In6\/Block/ { b6bi = \$6 };/Out6\/Block/ { b6bo = \$6 };\\\n";
390
			$rrdupdatesh .= "END {print b4pi \":\" b4po \":\" b4bi \":\" b4bo \":\" b6pi \":\" b6po \":\" b6bi \":\" b6bo};'`\n";
391

    
392
			/* PACKETS, set up the rrd file */
393
			if (!file_exists("$rrddbpath$ifname$packets")) {
394
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
395
				$rrdcreate .= "DS:inpass:COUNTER:$packetsvalid:0:$downstream ";
396
				$rrdcreate .= "DS:outpass:COUNTER:$packetsvalid:0:$upstream ";
397
				$rrdcreate .= "DS:inblock:COUNTER:$packetsvalid:0:$downstream ";
398
				$rrdcreate .= "DS:outblock:COUNTER:$packetsvalid:0:$upstream ";
399
				$rrdcreate .= "DS:inpass6:COUNTER:$packetsvalid:0:$downstream ";
400
				$rrdcreate .= "DS:outpass6:COUNTER:$packetsvalid:0:$upstream ";
401
				$rrdcreate .= "DS:inblock6:COUNTER:$packetsvalid:0:$downstream ";
402
				$rrdcreate .= "DS:outblock6:COUNTER:$packetsvalid:0:$upstream ";
403
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
404
				$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
405
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
406
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
407

    
408
				create_new_rrd($rrdcreate);
409
				unset($rrdcreate);
410
			}
411

    
412
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
413
			if (platform_booting()) {
414
				mwexec("$rrdtool update $rrddbpath$ifname$packets N:U:U:U:U:U:U:U:U");
415
			}
416

    
417
			$rrdupdatesh .= "\n";
418
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
419
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:";
420
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '\\\n";
421
			$rrdupdatesh .= "/In4\/Pass/ { b4pi = \$4 };/Out4\/Pass/ { b4po = \$4 };/In4\/Block/ { b4bi = \$4 };/Out4\/Block/ { b4bo = \$4 };\\\n";
422
			$rrdupdatesh .= "/In6\/Pass/ { b6pi = \$4 };/Out6\/Pass/ { b6po = \$4 };/In6\/Block/ { b6bi = \$4 };/Out6\/Block/ { b6bo = \$4 };\\\n";
423
			$rrdupdatesh .= "END {print b4pi \":\" b4po \":\" b4bi \":\" b4bo \":\" b6pi \":\" b6po \":\" b6bi \":\" b6bo};'`\n";
424

    
425
			/* WIRELESS, set up the rrd file */
426
			if ($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
427
				if (!file_exists("$rrddbpath$ifname$wireless")) {
428
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
429
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
430
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
431
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
432
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
433
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
434
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
435
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
436

    
437
					create_new_rrd($rrdcreate);
438
					unset($rrdcreate);
439
				}
440

    
441
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
442
				if (platform_booting()) {
443
					mwexec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
444
				}
445

    
446
				$rrdupdatesh .= "\n";
447
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
448
				$rrdupdatesh .= "WIFI=`$ifconfig {$realif} list sta| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
449
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\${WIFI}\n";
450
			}
451

    
452
			/* OpenVPN, set up the rrd file */
453
			if (stristr($ifname, "ovpns")) {
454
				if (!file_exists("$rrddbpath$ifname$vpnusers")) {
455
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$vpnusers --step $rrdvpninterval ";
456
					$rrdcreate .= "DS:users:GAUGE:$vpnvalid:0:10000 ";
457
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
458
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
459
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
460
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
461

    
462
					create_new_rrd($rrdcreate);
463
					unset($rrdcreate);
464
				}
465

    
466
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
467
				if (platform_booting()) {
468
					mwexec("$rrdtool update $rrddbpath$ifname$vpnusers N:U");
469
				}
470

    
471
				if (is_array($config['openvpn']['openvpn-server'])) {
472
					foreach ($config['openvpn']['openvpn-server'] as $server) {
473
						if ("ovpns{$server['vpnid']}" == $ifname) {
474
							$port = $server['local_port'];
475
							$vpnid = $server['vpnid'];
476
						}
477
					}
478
				}
479
				$rrdupdatesh .= "\n";
480
				$rrdupdatesh .= "# polling vpn users for interface $ifname $realif port $port\n";
481
				$rrdupdatesh .= "list_current_users() {\n";
482
				$rrdupdatesh .= " sleep 0.2\n";
483
				$rrdupdatesh .= " echo \"status 2\"\n";
484
				$rrdupdatesh .= " sleep 0.2\n";
485
				$rrdupdatesh .= " echo \"quit\"\n";
486
				$rrdupdatesh .= "}\n";
487
				$rrdupdatesh .= "OVPN=`list_current_users | nc -U {$g['varetc_path']}/openvpn/server{$vpnid}.sock | awk -F\",\" '/^CLIENT_LIST/ {print \$2}' | wc -l | awk '{print $1}'`\n";
488
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$vpnusers N:\${OVPN}\n";
489
			}
490

    
491
			/* QUEUES, set up the queues databases */
492
			if ($altq_list_queues[$ifname]) {
493
				$altq =& $altq_list_queues[$ifname];
494
				/* NOTE: Is it worth as its own function?! */
495
				switch ($altq->GetBwscale()) {
496
					case "Gb":
497
						$factor = 1024 * 1024 * 1024;
498
						break;
499
					case "Mb":
500
						$factor = 1024 * 1024;
501
						break;
502
					case "Kb":
503
						$factor = 1024;
504
						break;
505
					case "b":
506
					default:
507
						$factor = 1;
508
						break;
509
				}
510
				$qbandwidth = $altq->GetBandwidth() * $factor;
511
				if ($qbandwidth <= 0) {
512
					$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
513
				}
514
				$qlist =& $altq->get_queue_list($notused);
515
				if (!file_exists("$rrddbpath$ifname$queues")) {
516
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
517
					/* loop list of shaper queues */
518
					$q = 0;
519
					foreach ($qlist as $qname => $q) {
520
						$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
521
					}
522

    
523
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
524
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
525
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
526
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
527

    
528
					create_new_rrd($rrdcreate);
529
					unset($rrdcreate);
530
				}
531

    
532
				if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
533
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
534
					/* loop list of shaper queues */
535
					$q = 0;
536
					foreach ($qlist as $qname => $q) {
537
						$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
538
					}
539

    
540
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
541
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
542
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
543
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
544

    
545
					create_new_rrd($rrdcreate);
546
					unset($rrdcreate);
547
				}
548

    
549
				if (platform_booting()) {
550
					$rrdqcommand = "-t ";
551
					$rrducommand = "N";
552
					$qi = 0;
553
					foreach ($qlist as $qname => $q) {
554
						if ($qi == 0) {
555
							$rrdqcommand .= "{$qname}";
556
						} else {
557
							$rrdqcommand .= ":{$qname}";
558
						}
559
						$qi++;
560
						$rrducommand .= ":U";
561
					}
562
					mwexec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
563
					mwexec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
564
				}
565

    
566
				/* awk function to gather shaper data */
567
				/* yes, it's special */
568
				$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
569
				$rrdupdatesh .= "{ ";
570
				$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
571
				$rrdupdatesh .= " dsname = dsname \":\" \$2 ; ";
572
				$rrdupdatesh .= " q=1; ";
573
				$rrdupdatesh .= "} ";
574
				$rrdupdatesh .= " else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
575
				$rrdupdatesh .= " dsdata = dsdata \":\" \$5 ; ";
576
				$rrdupdatesh .= " q=0; ";
577
				$rrdupdatesh .= "} ";
578
				$rrdupdatesh .= "} END { ";
579
				$rrdupdatesh .= " dsname = substr(dsname,2); ";
580
				$rrdupdatesh .= " dsdata = substr(dsdata,2); ";
581
				$rrdupdatesh .= " printf \"-t \" dsname \" N:\" dsdata }' ";
582
				$rrdupdatesh .= " dsname=\"\" dsdata=\"\"`\n\n";
583

    
584
				$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
585
				$rrdupdatesh .= "{ ";
586
				$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
587
				$rrdupdatesh .= " dsname = dsname \":\" \$2 ; ";
588
				$rrdupdatesh .= " q=1; ";
589
				$rrdupdatesh .= "} ";
590
				$rrdupdatesh .= " else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
591
				$rrdupdatesh .= " dsdata = dsdata \":\" \$8 ; ";
592
				$rrdupdatesh .= " q=0; ";
593
				$rrdupdatesh .= "} ";
594
				$rrdupdatesh .= "} END { ";
595
				$rrdupdatesh .= " dsname = substr(dsname,2); ";
596
				$rrdupdatesh .= " dsdata = substr(dsdata,2); ";
597
				$rrdupdatesh .= " printf \"-t \" dsname \" N:\" dsdata }' ";
598
				$rrdupdatesh .= " dsname=\"\" dsdata=\"\"`\n\n";
599
			}
600

    
601
			/* 3G interfaces */
602
			if (preg_match("/ppp[0-9]+/i", $realif))	{
603
				if (!file_exists("$rrddbpath$ifname$cellular")) {
604
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$cellular --step $rrdcellularinterval ";
605
					$rrdcreate .= "DS:rssi:GAUGE:$cellularvalid:0:100 ";
606
					$rrdcreate .= "DS:upstream:GAUGE:$cellularvalid:0:100000000 ";
607
					$rrdcreate .= "DS:downstream:GAUGE:$cellularvalid:0:100000000 ";
608
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
609
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
610
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
611
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
612
					create_new_rrd($rrdcreate);
613
					unset($rrdcreate);
614
				}
615

    
616
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
617
				if (platform_booting()) {
618
					mwexec("$rrdtool update $rrddbpath$ifname$cellular N:U:U:U");
619
				}
620

    
621
				$rrdupdatesh .= "\n";
622
				$rrdupdatesh .= "# polling 3G\n";
623
				$rrdupdatesh .= "GSTATS=`awk -F, 'getline 2 {print \$2 \":\" \$8 \":\" \$9}' < /tmp/3gstats.$ifname`\n";
624
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$cellular N:\"\$GSTATS\"";
625
			}
626

    
627
		}
628
		$i++;
629

    
630
		/* System only statistics */
631
		$ifname = "system";
632

    
633
		/* STATES, create pf states database */
634
		if (!file_exists("$rrddbpath$ifname$states")) {
635
			$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
636
			$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
637
			$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
638
			$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
639
			$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
640
			$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
641
			$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
642
			$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
643
			$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
644
			$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
645

    
646
			create_new_rrd($rrdcreate);
647
			unset($rrdcreate);
648
		}
649

    
650
		/* enter UNKNOWN values in the RRD so it knows we rebooted. */
651
		if (platform_booting()) {
652
			mwexec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
653
		}
654

    
655
		/* the pf states gathering function. */
656
		$rrdupdatesh .= "\n";
657
		$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
658
		$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
659
		$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
660
		$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
661
		$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
662
		$rrdupdatesh .= "srcip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '\\->' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
663
		$rrdupdatesh .= "dstip=\"` cat /tmp/pfctl_ss_out | egrep -v '<\\-.*?<\\-|\\->.*?\\->' | grep '<\\-' | awk '{print \$3}' | awk -F: '{print \$1}' | sort -u|wc -l|sed 's/ //g' `\"\n";
664
		$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
665

    
666
		/* End pf states statistics */
667

    
668
		/* CPU, create CPU statistics database */
669
		if (!file_exists("$rrddbpath$ifname$proc")) {
670
			$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
671
			$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
672
			$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
673
			$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
674
			$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
675
			$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
676
			$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
677
			$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
678
			$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
679
			$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
680

    
681
			create_new_rrd($rrdcreate);
682
			unset($rrdcreate);
683
		}
684

    
685
		/* enter UNKNOWN values in the RRD so it knows we rebooted. */
686
		if (platform_booting()) {
687
			mwexec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
688
		}
689

    
690
		/* the CPU stats gathering function. */
691
		$rrdupdatesh .= "CPU=`$cpustats | cut -f1-4 -d':'`\n";
692
		/* Using ps uxaH will count all processes including system threads. Top was undercounting. */
693
		$rrdupdatesh .= "PROCS=`ps uxaH | wc -l | awk '{print \$1;}'`\n";
694
		$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$proc N:\${CPU}:\${PROCS}\n";
695

    
696
		/* End CPU statistics */
697

    
698
		/* Memory, create Memory statistics database */
699
		if (!file_exists("$rrddbpath$ifname$mem")) {
700
			$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
701
			$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
702
			$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
703
			$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
704
			$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
705
			$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
706
			$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
707
			$rrdcreate .= "RRA:MIN:0.5:5:720 ";
708
			$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
709
			$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
710
			$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
711
			$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
712
			$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
713
			$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
714
			$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
715
			$rrdcreate .= "RRA:MAX:0.5:5:720 ";
716
			$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
717
			$rrdcreate .= "RRA:MAX:0.5:1440:2284";
718

    
719
			create_new_rrd($rrdcreate);
720
			unset($rrdcreate);
721
		}
722

    
723
		/* enter UNKNOWN values in the RRD so it knows we rebooted. */
724
		if (platform_booting()) {
725
			mwexec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
726
		}
727

    
728
		/* the Memory stats gathering function. */
729
		$rrdupdatesh .= "MEM=`$sysctl -n vm.stats.vm.v_page_count vm.stats.vm.v_active_count vm.stats.vm.v_inactive_count vm.stats.vm.v_free_count vm.stats.vm.v_cache_count vm.stats.vm.v_wire_count | ";
730
		$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf ";
731
		$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n";
732
		$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$mem N:\${MEM}\n";
733

    
734
		/* End Memory statistics */
735

    
736
		/* mbuf, create mbuf statistics database */
737
		if (!file_exists("$rrddbpath$ifname$mbuf")) {
738
			$rrdcreate = "$rrdtool create $rrddbpath$ifname$mbuf --step $rrdmbufinterval ";
739
			$rrdcreate .= "DS:current:GAUGE:$mbufvalid:0:10000000 ";
740
			$rrdcreate .= "DS:cache:GAUGE:$mbufvalid:0:10000000 ";
741
			$rrdcreate .= "DS:total:GAUGE:$mbufvalid:0:10000000 ";
742
			$rrdcreate .= "DS:max:GAUGE:$mbufvalid:0:10000000 ";
743
			$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
744
			$rrdcreate .= "RRA:MIN:0.5:5:720 ";
745
			$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
746
			$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
747
			$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
748
			$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
749
			$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
750
			$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
751
			$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
752
			$rrdcreate .= "RRA:MAX:0.5:5:720 ";
753
			$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
754
			$rrdcreate .= "RRA:MAX:0.5:1440:2284";
755

    
756
			create_new_rrd($rrdcreate);
757
			unset($rrdcreate);
758
		}
759

    
760
		/* enter UNKNOWN values in the RRD so it knows we rebooted. */
761
		if (platform_booting()) {
762
			mwexec("$rrdtool update $rrddbpath$ifname$mbuf N:U:U:U:U");
763
		}
764

    
765
		/* the mbuf stats gathering function. */
766
		$rrdupdatesh .= "MBUF=`$netstat -m | ";
767
		$rrdupdatesh .= " $awk '/mbuf clusters in use/ { gsub(/\//, \":\", $1); print $1; }'`\n";
768
		$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$mbuf N:\${MBUF}\n";
769

    
770
		/* End mbuf statistics */
771

    
772
		/* SPAMD, set up the spamd rrd file */
773
		if (isset($config['installedpackages']['spamdsettings']) &&
774
		    $config['installedpackages']['spamdsettings']['config'][0]['enablerrd']) {
775
			/* set up the spamd rrd file */
776
			if (!file_exists("$rrddbpath$ifname$spamd")) {
777
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
778
				$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
779
				$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
780
				$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
781
				$rrdcreate .= "RRA:MIN:0.5:5:720 ";
782
				$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
783
				$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
784
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
785
				$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
786
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
787
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
788
				$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
789
				$rrdcreate .= "RRA:MAX:0.5:5:720 ";
790
				$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
791
				$rrdcreate .= "RRA:MAX:0.5:1440:2284 ";
792

    
793
				create_new_rrd($rrdcreate);
794
				unset($rrdcreate);
795
			}
796

    
797
			$rrdupdatesh .= "\n";
798
			$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
799
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
800
			$rrdupdatesh .= "`$php -q $spamd_gather`\n";
801

    
802
		}
803
		/* End System statistics */
804

    
805
		/* Captive Portal statistics, set up the rrd file */
806
		if (is_array($config['captiveportal'])) {
807
			foreach ($config['captiveportal'] as $cpkey => $cp) {
808
				if (!isset($cp['enable'])) {
809
					continue;
810
				}
811

    
812
				$ifname= "captiveportal";
813
				$concurrent_filename = $rrddbpath . $ifname . '-' . $cpkey . $captiveportalconcurrent;
814
				if (!file_exists("$concurrent_filename")) {
815
					$rrdcreate = "$rrdtool create $concurrent_filename --step $rrdcaptiveportalinterval ";
816
					$rrdcreate .= "DS:concurrentusers:GAUGE:$captiveportalvalid:0:10000 ";
817
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
818
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
819
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
820
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
821
					$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
822
					$rrdcreate .= "RRA:MIN:0.5:5:720 ";
823
					$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
824
					$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
825
					$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
826
					$rrdcreate .= "RRA:MAX:0.5:5:720 ";
827
					$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
828
					$rrdcreate .= "RRA:MAX:0.5:1440:2284 ";
829
					$rrdcreate .= "RRA:LAST:0.5:1:1200 ";
830
					$rrdcreate .= "RRA:LAST:0.5:5:720 ";
831
					$rrdcreate .= "RRA:LAST:0.5:60:1860 ";
832
					$rrdcreate .= "RRA:LAST:0.5:1440:2284 ";
833

    
834
					create_new_rrd($rrdcreate);
835
					unset($rrdcreate);
836
				}
837

    
838
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
839
				if (platform_booting()) {
840
					mwexec("$rrdtool update $concurrent_filename N:U");
841
				}
842

    
843
				/* the Captive Portal stats gathering function. */
844
				$rrdupdatesh .= "\n";
845
				$rrdupdatesh .= "# polling Captive Portal for number of concurrent users\n";
846
				$rrdupdatesh .= "CP=`${php} -q ${captiveportal_gather} '${cpkey}' 'concurrent'`\n";
847
				$rrdupdatesh .= "$rrdtool update $concurrent_filename \${CP}\n";
848

    
849
				$loggedin_filename = $rrddbpath . $ifname . '-' . $cpkey . $captiveportalloggedin;
850
				if (!file_exists("$loggedin_filename")) {
851
					$rrdcreate = "$rrdtool create $loggedin_filename --step $rrdcaptiveportalinterval ";
852
					$rrdcreate .= "DS:loggedinusers:GAUGE:$captiveportalvalid:0:10000 ";
853
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
854
					$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
855
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
856
					$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
857
					$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
858
					$rrdcreate .= "RRA:MIN:0.5:5:720 ";
859
					$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
860
					$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
861
					$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
862
					$rrdcreate .= "RRA:MAX:0.5:5:720 ";
863
					$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
864
					$rrdcreate .= "RRA:MAX:0.5:1440:2284 ";
865
					$rrdcreate .= "RRA:LAST:0.5:1:1200 ";
866
					$rrdcreate .= "RRA:LAST:0.5:5:720 ";
867
					$rrdcreate .= "RRA:LAST:0.5:60:1860 ";
868
					$rrdcreate .= "RRA:LAST:0.5:1440:2284 ";
869

    
870
					create_new_rrd($rrdcreate);
871
					unset($rrdcreate);
872
				}
873

    
874
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
875
				if (platform_booting()) {
876
					mwexec("$rrdtool update $loggedin_filename N:U");
877
				}
878

    
879
				/* the Captive Portal stats gathering function. */
880
				$rrdupdatesh .= "\n";
881
				$rrdupdatesh .= "# polling Captive Portal for number of logged in users\n";
882
				$rrdupdatesh .= "CP=`${php} -q ${captiveportal_gather} '${cpkey}' 'loggedin'`\n";
883
				$rrdupdatesh .= "$rrdtool update $loggedin_filename \${CP}\n";
884

    
885
			}
886
		}
887
		/* End Captive Portal statistics */
888

    
889
		/* NTP, set up the ntpd rrd file */
890
		if (isset($config['ntpd']['statsgraph'])) {
891
			/* set up the ntpd rrd file */
892
			if (!file_exists("$rrddbpath$ntpd")) {
893
				$rrdcreate = "$rrdtool create $rrddbpath$ntpd --step $rrdntpdinterval ";
894
				$rrdcreate .= "DS:offset:GAUGE:$ntpdvalid:-1000:1000 ";
895
				$rrdcreate .= "DS:sjit:GAUGE:$ntpdvalid:0:1000 ";
896
				$rrdcreate .= "DS:cjit:GAUGE:$ntpdvalid:0:1000 ";
897
				$rrdcreate .= "DS:wander:GAUGE:$ntpdvalid:0:1000 ";
898
				$rrdcreate .= "DS:freq:GAUGE:$ntpdvalid:0:1000 ";
899
				$rrdcreate .= "DS:disp:GAUGE:$ntpdvalid:0:1000 ";
900
				$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
901
				$rrdcreate .= "RRA:MIN:0.5:5:720 ";
902
				$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
903
				$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
904
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
905
				$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
906
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
907
				$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
908
				$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
909
				$rrdcreate .= "RRA:MAX:0.5:5:720 ";
910
				$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
911
				$rrdcreate .= "RRA:MAX:0.5:1440:2284 ";
912

    
913
				create_new_rrd($rrdcreate);
914
				unset($rrdcreate);
915
			}
916

    
917
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
918
			if (platform_booting()) {
919
				mwexec("$rrdtool update $rrddbpath$ntpd N:U:U:U:U:U:U");
920
			}
921

    
922
			/* the ntp stats gathering function. */
923
			$rrdupdatesh .= "\n";
924
			$rrdupdatesh .= "$ntpq -c rv | $awk 'BEGIN{ RS=\",\"}{ print }' >> /tmp/ntp-rrdstats.$$\n";
925
			$rrdupdatesh .= "NOFFSET=`grep offset /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
926
			$rrdupdatesh .= "NFREQ=`grep frequency /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
927
			$rrdupdatesh .= "NSJIT=`grep sys_jitter /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
928
			$rrdupdatesh .= "NCJIT=`grep clk_jitter /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
929
			$rrdupdatesh .= "NWANDER=`grep clk_wander /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
930
			$rrdupdatesh .= "NDISPER=`grep rootdisp /tmp/ntp-rrdstats.$$ | awk 'BEGIN{FS=\"=\"}{print $2}'`\n";
931
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ntpd \N:\${NOFFSET}:\${NSJIT}:\${NCJIT}:\${NWANDER}:\${NFREQ}:\${NDISPER}\n";
932
			$rrdupdatesh .= "rm /tmp/ntp-rrdstats.$$\n";
933
			$rrdupdatesh .= "\n";
934

    
935
		}
936
		/* End NTP statistics */
937

    
938
		/* Start dhcpd statistics */
939
		if (is_array($config['dhcpd'])) {
940
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
941
				if (isset($config['dhcpd'][$dhcpif]['statsgraph'])) {
942
					if (!file_exists("$rrddbpath$dhcpif$dhcpd")) {
943
						$rrdcreate = "$rrdtool create $rrddbpath$dhcpif$dhcpd --step $rrddhcpdinterval ";
944
						$rrdcreate .= "DS:leases:GAUGE:$dhcpdvalid:0:100000 ";
945
						$rrdcreate .= "DS:staticleases:GAUGE:$dhcpdvalid:0:100000 ";
946
						$rrdcreate .= "DS:dhcprange:GAUGE:$dhcpdvalid:0:100000 ";
947
						$rrdcreate .= "RRA:MIN:0.5:1:1200 ";
948
						$rrdcreate .= "RRA:MIN:0.5:5:720 ";
949
						$rrdcreate .= "RRA:MIN:0.5:60:1860 ";
950
						$rrdcreate .= "RRA:MIN:0.5:1440:2284 ";
951
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1200 ";
952
						$rrdcreate .= "RRA:AVERAGE:0.5:5:720 ";
953
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1860 ";
954
						$rrdcreate .= "RRA:AVERAGE:0.5:1440:2284 ";
955
						$rrdcreate .= "RRA:MAX:0.5:1:1200 ";
956
						$rrdcreate .= "RRA:MAX:0.5:5:720 ";
957
						$rrdcreate .= "RRA:MAX:0.5:60:1860 ";
958
						$rrdcreate .= "RRA:MAX:0.5:1440:2284 ";
959
						create_new_rrd($rrdcreate);
960
						unset($rrdcreate);
961
					}
962

    
963
					/* enter UNKNOWN values in the RRD so it knows we rebooted. */
964
					if (platform_booting()) {
965
						mwexec("$rrdtool update $rrddbpath$dhcpif$dhcpd N:U:U:U");
966
					}
967

    
968
					$rrdupdatesh .= "\n";
969
					$rrdupdatesh .= "# polling leases for dhcp \n";
970
					$rrdupdatesh .= "DHCP=`${php} -q ${dhcpd_gather} '${dhcpif}'`\n";
971
					$rrdupdatesh .= "$rrdtool update $rrddbpath$dhcpif$dhcpd \${DHCP}\n";
972

    
973
				}
974
			}
975
		}
976
		/* END dhcpd statistics */
977

    
978
		/* Start gateway quality */
979
		$rrdupdatesh .= <<<EOD
980

    
981
# Gateway quality graphs
982
for sock in {$g['varrun_path']}/dpinger_*.sock; do
983
	if [ ! -S "\$sock" ]; then
984
		continue
985
	fi
986

    
987
	t=\$(/usr/bin/nc -U \$sock)
988
	if [ -z "\$t" ]; then
989
		continue
990
	fi
991

    
992
	gw=\$(echo "\$t" | awk '{ print \$1 }')
993
	delay=\$(echo "\$t" | awk '{ print \$2 }')
994
	stddev=\$(echo "\$t" | awk '{ print \$3 }')
995
	loss=\$(echo "\$t" | awk '{ print \$4 }')
996

    
997
	if echo "\$loss" | grep -Eqv '^[0-9]+\$'; then
998
		loss="U"
999
	fi
1000
	if echo "\$delay" | grep -Eqv '^[0-9]+\$'; then
1001
		delay="U"
1002
	else
1003
		# Convert delay from microseconds to seconds
1004
		delay=\$(echo "scale=7; \$delay / 1000 / 1000" | /usr/bin/bc)
1005
	fi
1006
	if echo "\$stddev" | grep -Eqv '^[0-9]+\$'; then
1007
		stddev="U"
1008
	else
1009
		# Convert stddev from microseconds to seconds
1010
		stddev=\$(echo "scale=7; \$stddev / 1000 / 1000" | /usr/bin/bc)
1011
	fi
1012

    
1013
	if [ ! -f {$rrddbpath}\$gw-quality.rrd ]; then
1014
		{$rrdtool} create {$rrddbpath}\$gw-quality.rrd --step 60 \\
1015
		DS:loss:GAUGE:120:0:100 \\
1016
		DS:delay:GAUGE:120:0:100000 \\
1017
		DS:stddev:GAUGE:120:0:100000 \\
1018
		RRA:AVERAGE:0.5:1:1200 \\
1019
		RRA:AVERAGE:0.5:5:720 \\
1020
		RRA:AVERAGE:0.5:60:1860 \\
1021
		RRA:AVERAGE:0.5:1440:2284
1022

    
1023
		{$rrdtool} update {$rrddbpath}\$gw-quality.rrd -t loss:delay:stddev N:U:U:U
1024
	fi
1025

    
1026
	{$rrdtool} update {$rrddbpath}\$gw-quality.rrd -t loss:delay:stddev N:\$loss:\$delay:\$stddev
1027
done
1028

    
1029
EOD;
1030
		/* End gateway quality */
1031

    
1032
		$rrdupdatesh .= "sleep 60\n";
1033
		$rrdupdatesh .= "done\n";
1034
		log_error(gettext("Creating rrd update script"));
1035
		/* write the rrd update script */
1036
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
1037
		$fd = fopen("$updaterrdscript", "w");
1038
		fwrite($fd, "$rrdupdatesh");
1039
		fclose($fd);
1040

    
1041
		unset($rrdupdatesh);
1042

    
1043
		/* kill off traffic collectors */
1044
		kill_traffic_collector();
1045

    
1046
		/* start traffic collector */
1047
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
1048

    
1049
	} else {
1050
		/* kill off traffic collectors */
1051
		kill_traffic_collector();
1052
	}
1053

    
1054
	$databases = glob("{$rrddbpath}/*.rrd");
1055
	foreach ($databases as $database) {
1056
		if (file_exists($database)) {
1057
			chown($database, "nobody");
1058
		}
1059
	}
1060

    
1061
	if (platform_booting()) {
1062
		echo gettext("done.") . "\n";
1063
	}
1064

    
1065
}
1066

    
1067
function kill_traffic_collector() {
1068
	global $g;
1069

    
1070
	killbypid("{$g['varrun_path']}/updaterrd.sh.pid");
1071
}
1072

    
1073
?>
(46-46/65)