Project

General

Profile

Download (29.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
  Copyright (C) 2008 Seth Mos
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
  */
29

    
30
/*
31
	pfSense_BUILDER_BINARIES:	/bin/rm	/usr/bin/nice	/usr/local/bin/rrdtool	/bin/cd
32
	pfSense_MODULE:	rrd
33
*/
34

    
35
/* include all configuration functions */
36

    
37
function dump_rrd_to_xml($rrddatabase, $xmldumpfile) {
38
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
39
	if(file_exists($xmldumpfile))
40
		exec("rm {$xmldumpfile}");
41

    
42
	exec("$rrdtool dump {$rrddatabase} {$xmldumpfile} 2>&1", $dumpout, $dumpret);
43
	if ($dumpret <> 0) {
44
		$dumpout = implode(" ", $dumpout);
45
		log_error("RRD dump failed exited with $dumpret, the error is: $dumpout");
46
	}
47
	return($dumpret);
48
}
49

    
50
function create_new_rrd($rrdcreatecmd) {
51
	$rrdcreateoutput = array();
52
	$rrdcreatereturn = 0;
53
	exec("$rrdcreatecmd 2>&1", $rrdcreateoutput, $rrdcreatereturn);
54
	if ($rrdcreatereturn <> 0) {
55
		$rrdcreateoutput = implode(" ", $rrdcreateoutput);
56
		log_error("RRD create failed exited with $rrdcreatereturn, the error is: $rrdcreateoutput");
57
	}
58
	return $rrdcreatereturn;
59
}
60

    
61
function migrate_rrd_format($rrdoldxml, $rrdnewxml) {
62
	if(!file_exists("/tmp/rrd_notice_sent.txt")) {
63
		exec("echo 'Converting RRD configuration to new format.  This might take a bit...' | wall");
64
		touch("/tmp/rrd_notice_sent.txt");
65
	}
66
	$numrraold = count($rrdoldxml['rra']);
67
	$numdsold = count($rrdoldxml['ds']);
68
	$numrranew = count($rrdnewxml['rra']);
69
	$numdsnew = count($rrdnewxml['ds']);
70
	log_error("Import RRD has $numdsold DS values and $numrraold RRA databases, new format RRD has $numdsnew DS values and $numrranew RRA databases");
71
	
72
	/* add data sources not found in the old array from the new array */
73
	$i = 0;
74
	foreach($rrdnewxml['ds'] as $ds) {
75
		if(!is_array($rrdoldxml['ds'][$i])) {
76
			$rrdoldxml['ds'][$i] = $rrdnewxml['ds'][$i];
77
			/* set unknown values to 0 */
78
			$rrdoldxml['ds'][$i]['last_ds'] = " 0.0000000000e+00 ";
79
			$rrdoldxml['ds'][$i]['value'] = " 0.0000000000e+00 ";
80
			$rrdoldxml['ds'][$i]['unknown_sec'] = "0";
81
		}
82
		$i++;
83
	}
84

    
85
	$i = 0;
86
	$rracountold = count($rrdoldxml['rra']);
87
	$rracountnew = count($rrdnewxml['rra']);
88
	/* process each RRA, which contain a database */
89
	foreach($rrdnewxml['rra'] as $rra) {
90
		if(!is_array($rrdoldxml['rra'][$i])) {
91
			$rrdoldxml['rra'][$i] = $rrdnewxml['rra'][$i];
92
		}
93

    
94
		$d = 0;
95
		/* process cdp_prep */
96
		$cdp_prep = $rra['cdp_prep'];
97
		foreach($cdp_prep['ds'] as $ds) {
98
			if(!is_array($rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d])) {
99
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d] = $rrdnewxml['rra'][$i]['cdp_prep']['ds'][$d];
100
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['primary_value'] = " 0.0000000000e+00 ";
101
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['secondary_value'] = " 0.0000000000e+00 ";
102
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['value'] = " 0.0000000000e+00 ";
103
				$rrdoldxml['rra'][$i]['cdp_prep']['ds'][$d]['unknown_datapoints'] = "0";
104
			}
105
			$d++;
106
		}
107

    
108
		/* process database */
109
		$rows = $rra['database'];
110
		$k = 0;
111
		$rowcountold = count($rrdoldxml['rra'][$i]['database']['row']);
112
		$rowcountnew = count($rrdnewxml['rra'][$i]['database']['row']);
113
		$rowcountdiff = $rowcountnew - $rowcountold;
114
		/* save old rows for a bit before we put the required empty rows before it */
115
		$rowsdata = $rows;
116
		$rowsempty = array();
117
		$r = 0;
118
		while($r < $rowcountdiff) {
119
			$rowsempty[] = $rrdnewxml['rra'][$i]['database']['row'][$r];
120
			$r++;
121
		}
122
		$rows = $rowsempty + $rowsdata;
123
		/* now foreach the rows in the database */
124
		foreach($rows['row'] as $row) {
125
			if(!is_array($rrdoldxml['rra'][$i]['database']['row'][$k])) {
126
				$rrdoldxml['rra'][$i]['database']['row'][$k] = $rrdnewxml['rra'][$i]['database']['row'][$k];
127
			}
128
			$m = 0;
129
			$vcountold = count($rrdoldxml['rra'][$i]['database']['row'][$k]['v']);
130
			$vcountnew = count($rrdnewxml['rra'][$i]['database']['row'][$k]['v']);
131
			foreach($row['v'] as $value) {
132
				if(empty($rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m])) {
133
					if(isset($valid)) {
134
						$rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m] = "0.0000000000e+00 ";
135
					} else {
136
						$rrdoldxml['rra'][$i]['database']['row'][$k]['v'][$m] = $rrdnewxml['rra'][$i]['database']['row'][$k]['v'][$m];
137
					}
138
				} else {
139
					if($value <> " NaN ") {
140
						$valid = true;
141
					} else {
142
						$valid = false;
143
					}
144
				}
145
				$m++;
146
			}
147
			$k++;
148
		}
149
		$i++;
150
	}
151

    
152
	$numrranew = count($rrdoldxml['rra']);
153
	$numdsnew = count($rrdoldxml['ds']);
154
	log_error("The new RRD now has $numdsnew DS values and $numrranew RRA databases");
155
	return $rrdoldxml;
156
}
157

    
158
function enable_rrd_graphing() {
159
	global $config, $g, $altq_list_queues;
160

    
161
	if($g['booting']) 
162
		echo "Generating RRD graphs...";
163

    
164
	$rrddbpath = "/var/db/rrd/";
165
	$rrdgraphpath = "/usr/local/www/rrd";
166

    
167
	$traffic = "-traffic.rrd";
168
	$packets = "-packets.rrd";
169
	$states = "-states.rrd";
170
	$wireless = "-wireless.rrd";
171
	$queues = "-queues.rrd";
172
	$queuesdrop = "-queuedrops.rrd";
173
	$spamd = "-spamd.rrd";
174
	$proc = "-processor.rrd";
175
	$mem = "-memory.rrd";
176
	$cellular = "-cellular.rrd";
177

    
178
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
179
	$netstat = "/usr/bin/netstat";
180
	$awk = "/usr/bin/awk";
181
	$tar = "/usr/bin/tar";
182
	$pfctl = "/sbin/pfctl";
183
	$sysctl = "/sbin/sysctl";
184
	$php = "/usr/local/bin/php";
185
	$top = "/usr/bin/top";
186
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
187
	$ifconfig = "/sbin/ifconfig";
188

    
189
	$rrdtrafficinterval = 60;
190
	$rrdwirelessinterval = 60;
191
	$rrdqueuesinterval = 60;
192
	$rrdqueuesdropinterval = 60;
193
	$rrdpacketsinterval = 60;
194
	$rrdstatesinterval = 60;
195
	$rrdspamdinterval = 60;
196
	$rrdlbpoolinterval = 60;
197
	$rrdprocinterval = 60;
198
	$rrdmeminterval = 60;
199
	$rrdcellularinterval = 60;
200

    
201
	$trafficvalid = $rrdtrafficinterval * 2;
202
	$wirelessvalid = $rrdwirelessinterval * 2;
203
	$queuesvalid = $rrdqueuesinterval * 2;
204
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
205
	$packetsvalid = $rrdpacketsinterval * 2;
206
	$statesvalid = $rrdstatesinterval*2;
207
	$spamdvalid = $rrdspamdinterval * 2;
208
	$lbpoolvalid = $rrdlbpoolinterval * 2;
209
	$procvalid = $rrdlbpoolinterval * 2;
210
	$memvalid = $rrdmeminterval * 2;
211
	$cellularvalid = $rrdcellularinterval * 2;
212

    
213
	/* Asume GigE for now */
214
	$downstream = 125000000;
215
	$upstream = 125000000;
216

    
217
	/* read the shaper config */
218
	read_altq_config();
219

    
220
	$rrdrestore = "";
221
	$rrdreturn = "";
222

    
223
	if (isset ($config['rrd']['enable'])) {
224

    
225
		/* create directory if needed */
226
		if (!is_dir("$rrddbpath")) {
227
			mkdir("$rrddbpath", 0755);
228
		}
229

    
230
		if ($g['booting']) {
231
			if ($g['platform'] != "pfSense") {
232
				/* restore the databases, if we have one */
233
				if (file_exists("{$g['cf_conf_path']}/rrd.tgz")) {
234
					exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/rrd.tgz 2>&1", $rrdrestore, $rrdreturn);
235
					$rrdrestore = implode(" ", $rrdrestore);
236
					if($rrdreturn <> 0) {
237
						log_error("RRD restore failed exited with $rrdreturn, the error is: $rrdrestore\n");
238
					}
239
				}
240
			}
241
		}
242

    
243
		/* db update script */
244
		$rrdupdatesh = "#!/bin/sh\n";
245
		$rrdupdatesh .= "\n";
246
		$rrdupdatesh .= "counter=1\n";
247
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
248
		$rrdupdatesh .= "do\n";
249
		$rrdupdatesh .= "";
250

    
251
		$i = 0;
252
		$ifdescrs = get_configured_interface_with_descr();
253
		$ifdescrs['ipsec'] = "IPsec";
254

    
255
		foreach ($ifdescrs as $ifname => $ifdescr) {
256
			$temp = get_real_interface($ifname);
257
			if($temp <> "") {
258
				$realif = $temp;
259
			}
260

    
261
			/* TRAFFIC, set up the rrd file */
262
			if (!file_exists("$rrddbpath$ifname$traffic")) {
263
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
264
				$rrdcreate .= "DS:inpass:COUNTER:$trafficvalid:0:$downstream ";
265
				$rrdcreate .= "DS:outpass:COUNTER:$trafficvalid:0:$upstream ";
266
				$rrdcreate .= "DS:inblock:COUNTER:$trafficvalid:0:$downstream ";
267
				$rrdcreate .= "DS:outblock:COUNTER:$trafficvalid:0:$upstream ";
268
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
269
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
270
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
271
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
272

    
273
				create_new_rrd($rrdcreate);
274
			}
275

    
276
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
277
			if($g['booting']) {
278
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U:U:U");
279
			}
280

    
281
			$rrdupdatesh .= "\n";
282
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
283
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
284
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Pass|Out4\/Pass/ {printf \$6 \":\"}'`\\\n";
285
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Block|Out4\/Block/ {printf \$6 \":\"}'|sed -e 's/.\$//'`\n";
286

    
287
			/* PACKETS, set up the rrd file */
288
			if (!file_exists("$rrddbpath$ifname$packets")) {
289
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
290
				$rrdcreate .= "DS:inpass:COUNTER:$packetsvalid:0:$downstream ";
291
				$rrdcreate .= "DS:outpass:COUNTER:$packetsvalid:0:$upstream ";
292
				$rrdcreate .= "DS:inblock:COUNTER:$packetsvalid:0:$downstream ";
293
				$rrdcreate .= "DS:outblock:COUNTER:$packetsvalid:0:$upstream ";
294
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
295
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
296
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
297
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
298

    
299
				create_new_rrd($rrdcreate);
300
			}
301

    
302
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
303
			if($g['booting']) {
304
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U:U:U");
305
			}
306

    
307
			$rrdupdatesh .= "\n";
308
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
309
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
310
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Pass|Out4\/Pass/ {printf \$4 \":\"}'`\\\n";
311
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Block|Out4\/Block/ {printf \$4 \":\"}'|sed -e 's/.\$//'`\n";
312

    
313
			/* WIRELESS, set up the rrd file */
314
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
315
				if (!file_exists("$rrddbpath$ifname$wireless")) {
316
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
317
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
318
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
319
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
320
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
321
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
322
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
323
					$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
324
	
325
					create_new_rrd($rrdcreate);
326
				}
327

    
328
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
329
				if($g['booting']) {
330
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
331
				}
332

    
333
				$rrdupdatesh .= "\n";
334
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
335
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
336
				$rrdupdatesh .= "`$ifconfig {$realif} list sta| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
337
			}
338

    
339
				/* QUEUES, set up the queues databases */
340
				if ($altq_list_queues[$ifname]) {
341
					$altq =& $altq_list_queues[$ifname];
342
					/* NOTE: Is it worth as its own function?! */
343
					switch ($altq->GetBwscale()) {
344
                                        case "Gb":
345
                                        	$factor = 1024 * 1024 * 1024;
346
                                                break;
347
                                        case "Mb":
348
                                                $factor = 1024 * 1024;
349
                                                break;
350
                                        case "Kb":
351
                                                $factor = 1024;
352
                                                break;
353
                                        case "b":
354
                                        default:
355
                                                $factor = 1;
356
                                                break;
357
                                        }
358
					$qbandwidth = $altq->GetBandwidth() * $factor;
359
					if ($qbandwidth <=0)
360
						$qbandwidth = 100 * 1000 * 1000; /* 100Mbit */
361
					$qlist =& $altq->get_queue_list($notused);
362
					if (!file_exists("$rrddbpath$ifname$queues")) {
363
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queues --step $rrdqueuesinterval ";
364
						/* loop list of shaper queues */
365
						$q = 0;
366
						foreach ($qlist as $qname => $q) {
367
							$rrdcreate .= "DS:$qname:COUNTER:$queuesvalid:0:$qbandwidth ";
368
						}
369

    
370
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
371
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
372
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
373
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
374

    
375
						create_new_rrd($rrdcreate);
376
					}
377

    
378
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
379
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
380
						/* loop list of shaper queues */
381
						$q = 0;
382
						foreach ($qlist as $qname => $q) {
383
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
384
						}
385

    
386
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
387
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
388
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
389
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
390

    
391
						create_new_rrd($rrdcreate);
392
					}
393

    
394
					if($g['booting']) {
395
						$rrdqcommand = "-t ";
396
						$rrducommand = "N";
397
						$q = 0;
398
						foreach ($qlist as $qname => $q) {
399
							if($q == 0) {
400
								$rrdqcommand .= "{$qname}";
401
							} else {
402
								$rrdqcommand .= ":{$qname}";
403
							}
404
							$q++;
405
							$rrducommand .= ":U";
406
						}
407
						mwexec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
408
						mwexec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
409
					}
410

    
411
					/* awk function to gather shaper data */
412
					/* yes, it's special */
413
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
414
					$rrdupdatesh .= "{ ";
415
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
416
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
417
					$rrdupdatesh .= "q=1; ";
418
					$rrdupdatesh .= "} ";
419
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
420
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
421
					$rrdupdatesh .= "q=0; ";
422
					$rrdupdatesh .= "} ";
423
					$rrdupdatesh .= "} END { ";
424
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
425
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
426
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
427
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
428

    
429
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
430
					$rrdupdatesh .= "{ ";
431
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
432
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
433
					$rrdupdatesh .= "q=1; ";
434
					$rrdupdatesh .= "} ";
435
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
436
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
437
					$rrdupdatesh .= "q=0; ";
438
					$rrdupdatesh .= "} ";
439
					$rrdupdatesh .= "} END { ";
440
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
441
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
442
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
443
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
444
				}
445
		}
446
		$i++;
447

    
448
		/* System only statistics */
449
		$ifname = "system";
450

    
451
			/* STATES, create pf states database */
452
			if(! file_exists("$rrddbpath$ifname$states")) {
453
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
454
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
455
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
456
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
457
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
458
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
459
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
460
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
461
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
462
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
463

    
464
				create_new_rrd($rrdcreate);
465
			}
466

    
467
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
468
			if($g['booting']) {
469
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
470
			}
471

    
472
 			/* the pf states gathering function. */
473
 			$rrdupdatesh .= "\n";
474
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
475
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
476
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
477
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
478
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
479
 			$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";
480
 			$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";
481
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
482

    
483
			/* End pf states statistics */
484

    
485
			/* CPU, create CPU statistics database */
486
			if(! file_exists("$rrddbpath$ifname$proc")) {
487
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
488
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
489
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
490
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
491
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
492
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
493
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
494
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
495
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
496
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
497

    
498
				create_new_rrd($rrdcreate);
499
			}
500

    
501
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
502
			if($g['booting']) {
503
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
504
			}
505

    
506
 			/* the CPU stats gathering function. */
507
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\\n";
508
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\\n";
509
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { processes = \$1; } \\\n";
510
			$rrdupdatesh .= "else if ( \$1 == \"CPU:\" ) { user = \$2; nice = \$4; sys = \$6; interrupt = \$8; } \\\n";
511
			$rrdupdatesh .= "} END { printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes }'`\n\n";
512

    
513
			/* End CPU statistics */
514

    
515
			/* Memory, create Memory statistics database */
516
			if(! file_exists("$rrddbpath$ifname$mem")) {
517
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
518
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
519
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
520
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
521
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
522
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
523
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
524
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
525
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
526
				$rrdcreate .= "RRA:MIN:0.5:720:3000 ";
527
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
528
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
529
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
530
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
531
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
532
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
533
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
534
				$rrdcreate .= "RRA:MAX:0.5:720:3000";
535

    
536
				create_new_rrd($rrdcreate);
537
			}
538

    
539
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
540
			if($g['booting']) {
541
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
542
			}
543

    
544
 			/* the Memory stats gathering function. */
545
 			$rrdupdatesh .= "`$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 | ";
546
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
547
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
548
			
549
			/* End Memory statistics */
550

    
551
			/* SPAMD, set up the spamd rrd file */
552
			if (isset($config['installedpackages']['spamdsettings']) &&
553
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
554
				/* set up the spamd rrd file */
555
				if (!file_exists("$rrddbpath$ifname$spamd")) {
556
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
557
					$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
558
					$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
559
					$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
560
					$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
561
					$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
562
					$rrdcreate .= "RRA:MIN:0.5:720:3000 ";
563
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
564
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
565
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
566
					$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
567
					$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
568
					$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
569
					$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
570
					$rrdcreate .= "RRA:MAX:0.5:720:3000 ";
571

    
572
					create_new_rrd($rrdcreate);
573
				}
574

    
575
				$rrdupdatesh .= "\n";
576
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
577
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
578
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
579

    
580
			}
581
		/* End System statistics */
582

    
583
		/* 3G WIRELESS, set up the rrd file */
584
		if(isset($config['ppps']['ppp'])) {
585
			$ifname = "ppp";
586
			if (!file_exists("$rrddbpath$ifname$cellular")) {
587
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$cellular --step $rrdcellularinterval ";
588
				$rrdcreate .= "DS:signal1:GAUGE:$cellularvalid:-200:200 ";
589
				$rrdcreate .= "DS:signal2:GAUGE:$cellularvalid:-200:200 ";
590
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
591
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
592
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
593
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
594

    
595
				create_new_rrd($rrdcreate);
596
			}
597

    
598
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
599
			if($g['booting']) {
600
				exec("$rrdtool update $rrddbpath$ifname$cellular N:U:U");
601
			}
602

    
603
			$rrdupdatesh .= "\n";
604
			$rrdupdatesh .= "# polling 3G\n";
605
			$rrdupdatesh .= "dev=`usbconfig show_ifdrv | awk -F. '/ u3g|umodem/ {print \"/dev/\" $1 \".\" $2}'`\n";
606
			$rrdupdatesh .= "if [ -n \"\$dev\" ]; then $rrdtool update $rrddbpath$ifname$cellular N:`3gstat -s -d \$dev`\n";
607
			$rrdupdatesh .= "else $rrdtool update $rrddbpath$ifname$cellular N:U:U; fi\n";
608
		}
609

    
610

    
611
		$rrdupdatesh .= "sleep 60\n";
612
		$rrdupdatesh .= "done\n";
613
		log_error("Creating rrd update script");
614
		/* write the rrd update script */
615
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
616
		$fd = fopen("$updaterrdscript", "w");
617
		fwrite($fd, "$rrdupdatesh");
618
		fclose($fd);
619

    
620
		/* kill off traffic collectors */
621
		kill_traffic_collector();
622

    
623
		/* start traffic collector */
624
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
625

    
626
	} else {
627
		/* kill off traffic collectors */
628
		kill_traffic_collector();
629
	}
630

    
631
	if($g['booting']) 
632
		echo "done.\n";
633
		
634
}
635

    
636
function kill_traffic_collector() {
637
	mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill 2>&1");
638
}
639

    
640
/* This xml 2 array function is courtesy of the php.net comment section on xml_parse.
641
 * it is roughly 4 times faster then our existing pfSense parser but due to the large
642
 * size of the RRD xml dumps this is required.
643
 * The reason we do not use it for pfSense is that it does not know about array fields
644
 * which causes it to fail on array fields with single items. Possible Todo?
645
 */
646
function xml2array($contents, $get_attributes = 1, $priority = 'tag')
647
{
648
    if (!function_exists('xml_parser_create'))
649
    {
650
        return array ();
651
    }
652
    $parser = xml_parser_create('');
653
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
654
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
655
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
656
    xml_parse_into_struct($parser, trim($contents), $xml_values);
657
    xml_parser_free($parser);
658
    if (!$xml_values)
659
        return; //Hmm...
660
    $xml_array = array ();
661
    $parents = array ();
662
    $opened_tags = array ();
663
    $arr = array ();
664
    $current = & $xml_array;
665
    $repeated_tag_index = array ();
666
    foreach ($xml_values as $data)
667
    {
668
        unset ($attributes, $value);
669
        extract($data);
670
        $result = array ();
671
        $attributes_data = array ();
672
        if (isset ($value))
673
        {
674
            if ($priority == 'tag')
675
                $result = $value;
676
            else
677
                $result['value'] = $value;
678
        }
679
        if (isset ($attributes) and $get_attributes)
680
        {
681
            foreach ($attributes as $attr => $val)
682
            {
683
                if ($priority == 'tag')
684
                    $attributes_data[$attr] = $val;
685
                else
686
                    $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
687
            }
688
        }
689
        if ($type == "open")
690
        {
691
            $parent[$level -1] = & $current;
692
            if (!is_array($current) or (!in_array($tag, array_keys($current))))
693
            {
694
                $current[$tag] = $result;
695
                if ($attributes_data)
696
                    $current[$tag . '_attr'] = $attributes_data;
697
                $repeated_tag_index[$tag . '_' . $level] = 1;
698
                $current = & $current[$tag];
699
            }
700
            else
701
            {
702
                if (isset ($current[$tag][0]))
703
                {
704
                    $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
705
                    $repeated_tag_index[$tag . '_' . $level]++;
706
                }
707
                else
708
                {
709
                    $current[$tag] = array (
710
                        $current[$tag],
711
                        $result
712
                    );
713
                    $repeated_tag_index[$tag . '_' . $level] = 2;
714
                    if (isset ($current[$tag . '_attr']))
715
                    {
716
                        $current[$tag]['0_attr'] = $current[$tag . '_attr'];
717
                        unset ($current[$tag . '_attr']);
718
                    }
719
                }
720
                $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
721
                $current = & $current[$tag][$last_item_index];
722
            }
723
        }
724
        elseif ($type == "complete")
725
        {
726
            if (!isset ($current[$tag]))
727
            {
728
                $current[$tag] = $result;
729
                $repeated_tag_index[$tag . '_' . $level] = 1;
730
                if ($priority == 'tag' and $attributes_data)
731
                    $current[$tag . '_attr'] = $attributes_data;
732
            }
733
            else
734
            {
735
                if (isset ($current[$tag][0]) and is_array($current[$tag]))
736
                {
737
                    $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
738
                    if ($priority == 'tag' and $get_attributes and $attributes_data)
739
                    {
740
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
741
                    }
742
                    $repeated_tag_index[$tag . '_' . $level]++;
743
                }
744
                else
745
                {
746
                    $current[$tag] = array (
747
                        $current[$tag],
748
                        $result
749
                    );
750
                    $repeated_tag_index[$tag . '_' . $level] = 1;
751
                    if ($priority == 'tag' and $get_attributes)
752
                    {
753
                        if (isset ($current[$tag . '_attr']))
754
                        {
755
                            $current[$tag]['0_attr'] = $current[$tag . '_attr'];
756
                            unset ($current[$tag . '_attr']);
757
                        }
758
                        if ($attributes_data)
759
                        {
760
                            $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
761
                        }
762
                    }
763
                    $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
764
                }
765
            }
766
        }
767
        elseif ($type == 'close')
768
        {
769
            $current = & $parent[$level -1];
770
        }
771
    }
772
    return ($xml_array);
773
}
774

    
775
?>
(34-34/50)