Project

General

Profile

Download (28.3 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

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

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

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

    
210
	/* Asume GigE for now */
211
	$downstream = 125000000;
212
	$upstream = 125000000;
213

    
214
	/* read the shaper config */
215
	read_altq_config();
216

    
217
	$rrdrestore = "";
218
	$rrdreturn = "";
219

    
220
	if (isset ($config['rrd']['enable'])) {
221

    
222
		/* create directory if needed */
223
		if (!is_dir("$rrddbpath")) {
224
			mkdir("$rrddbpath", 0755);
225
		}
226

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

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

    
248
		$i = 0;
249
		$vfaces = array (
250
			"vlan.?*",
251
			"enc.?*"
252
		);
253
		$ifdescrs = get_interface_list(true, true, $vfaces);
254
		$ifdescrs['enc0']['friendly'] = "ipsec";
255
		$ifdescrs['enc0']['descr'] = "IPsec";
256
		$ifdescrs['enc0']['up'] = true;
257

    
258
		foreach ($ifdescrs as $realif => $ifdescr) {
259
			$ifname = $ifdescr['friendly'];
260
			$state = $ifdescr['up'];
261
			$realif = get_real_interface($ifname);
262

    
263
			/* skip interfaces that do not have a friendly name */
264
			if ("$ifname" == "") {
265
				continue;
266
			}
267

    
268
			/* or are down */
269
			if (!$state) {
270
				continue;
271
			}
272

    
273
			/* TRAFFIC, set up the rrd file */
274
			if (!file_exists("$rrddbpath$ifname$traffic")) {
275
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$traffic --step $rrdtrafficinterval ";
276
				$rrdcreate .= "DS:inpass:COUNTER:$trafficvalid:0:$downstream ";
277
				$rrdcreate .= "DS:outpass:COUNTER:$trafficvalid:0:$upstream ";
278
				$rrdcreate .= "DS:inblock:COUNTER:$trafficvalid:0:$downstream ";
279
				$rrdcreate .= "DS:outblock:COUNTER:$trafficvalid:0:$upstream ";
280
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
281
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
282
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
283
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
284

    
285
				create_new_rrd($rrdcreate);
286
			}
287

    
288
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
289
			if($g['booting']) {
290
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U:U:U");
291
			}
292

    
293
			$rrdupdatesh .= "\n";
294
			$rrdupdatesh .= "# polling traffic for interface $ifname $realif \n";
295
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$traffic N:\\\n";
296
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Pass|Out4\/Pass/ {printf \$6 \":\"}'`\\\n";
297
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Block|Out4\/Block/ {printf \$6 \":\"}'|sed -e 's/.\$//'`\n";
298

    
299
			/* PACKETS, set up the rrd file */
300
			if (!file_exists("$rrddbpath$ifname$packets")) {
301
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$packets --step $rrdpacketsinterval ";
302
				$rrdcreate .= "DS:inpass:COUNTER:$packetsvalid:0:$downstream ";
303
				$rrdcreate .= "DS:outpass:COUNTER:$packetsvalid:0:$upstream ";
304
				$rrdcreate .= "DS:inblock:COUNTER:$packetsvalid:0:$downstream ";
305
				$rrdcreate .= "DS:outblock:COUNTER:$packetsvalid:0:$upstream ";
306
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
307
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
308
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
309
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
310

    
311
				create_new_rrd($rrdcreate);
312
			}
313

    
314
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
315
			if($g['booting']) {
316
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U:U:U");
317
			}
318

    
319
			$rrdupdatesh .= "\n";
320
			$rrdupdatesh .= "# polling packets for interface $ifname $realif \n";
321
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$packets N:\\\n";
322
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Pass|Out4\/Pass/ {printf \$4 \":\"}'`\\\n";
323
			$rrdupdatesh .= "`$pfctl -vvsI -i {$realif} | awk '/In4\/Block|Out4\/Block/ {printf \$4 \":\"}'|sed -e 's/.\$//'`\n";
324

    
325
			/* WIRELESS, set up the rrd file */
326
			if($config['interfaces'][$ifname]['wireless']['mode'] == "bss") {
327
				if (!file_exists("$rrddbpath$ifname$wireless")) {
328
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$wireless --step $rrdwirelessinterval ";
329
					$rrdcreate .= "DS:snr:GAUGE:$wirelessvalid:0:1000 ";
330
					$rrdcreate .= "DS:rate:GAUGE:$wirelessvalid:0:1000 ";
331
					$rrdcreate .= "DS:channel:GAUGE:$wirelessvalid:0:1000 ";
332
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
333
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
334
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
335
					$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
336
	
337
					create_new_rrd($rrdcreate);
338
				}
339

    
340
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
341
				if($g['booting']) {
342
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
343
				}
344

    
345
				$rrdupdatesh .= "\n";
346
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
347
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
348
				$rrdupdatesh .= "`$ifconfig {$realif} list sta| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
349
			}
350

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

    
382
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
383
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
384
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
385
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
386

    
387
						create_new_rrd($rrdcreate);
388
					}
389

    
390
					if (!file_exists("$rrddbpath$ifname$queuesdrop")) {
391
						$rrdcreate = "$rrdtool create $rrddbpath$ifname$queuesdrop --step $rrdqueuesdropinterval ";
392
						/* loop list of shaper queues */
393
						$q = 0;
394
						foreach ($qlist as $qname => $q) {
395
							$rrdcreate .= "DS:$qname:COUNTER:$queuesdropvalid:0:$qbandwidth ";
396
						}
397

    
398
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
399
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
400
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
401
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
402

    
403
						create_new_rrd($rrdcreate);
404
					}
405

    
406
					if($g['booting']) {
407
						$rrdqcommand = "-t ";
408
						$rrducommand = "N";
409
						$q = 0;
410
						foreach ($qlist as $qname => $q) {
411
							if($q == 0) {
412
								$rrdqcommand .= "{$qname}";
413
							} else {
414
								$rrdqcommand .= ":{$qname}";
415
							}
416
							$q++;
417
							$rrducommand .= ":U";
418
						}
419
						mwexec("$rrdtool update $rrddbpath$ifname$queues $rrdqcommand $rrducommand");
420
						mwexec("$rrdtool update $rrddbpath$ifname$queuesdrop $rrdqcommand $rrducommand");
421
					}
422

    
423
					/* awk function to gather shaper data */
424
					/* yes, it's special */
425
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queues \" } ";
426
					$rrdupdatesh .= "{ ";
427
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
428
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
429
					$rrdupdatesh .= "q=1; ";
430
					$rrdupdatesh .= "} ";
431
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
432
					$rrdupdatesh .= "dsdata = dsdata \":\" \$5 ; ";
433
					$rrdupdatesh .= "q=0; ";
434
					$rrdupdatesh .= "} ";
435
					$rrdupdatesh .= "} END { ";
436
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
437
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
438
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
439
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
440

    
441
					$rrdupdatesh .= "` pfctl -vsq -i {$realif} | awk 'BEGIN {printf \"$rrdtool update $rrddbpath$ifname$queuesdrop \" } ";
442
					$rrdupdatesh .= "{ ";
443
					$rrdupdatesh .= "if ((\$1 == \"queue\") && ( \$2 ~ /^q/ )) { ";
444
					$rrdupdatesh .= "dsname = dsname \":\" \$2 ; ";
445
					$rrdupdatesh .= "q=1; ";
446
					$rrdupdatesh .= "} ";
447
					$rrdupdatesh .= "else if ((\$4 == \"bytes:\") && ( q == 1 ) ) { ";
448
					$rrdupdatesh .= "dsdata = dsdata \":\" \$8 ; ";
449
					$rrdupdatesh .= "q=0; ";
450
					$rrdupdatesh .= "} ";
451
					$rrdupdatesh .= "} END { ";
452
					$rrdupdatesh .= "dsname = substr(dsname,2); ";
453
					$rrdupdatesh .= "dsdata = substr(dsdata,2); ";
454
					$rrdupdatesh .= "printf \"-t \" dsname \" N:\" dsdata }' ";
455
					$rrdupdatesh .= "dsname=\"\" dsdata=\"\"`\n\n";
456
				}
457
		}
458
		$i++;
459

    
460
		/* System only statistics */
461
		$ifname = "system";
462

    
463
			/* STATES, create pf states database */
464
			if(! file_exists("$rrddbpath$ifname$states")) {
465
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$states --step $rrdstatesinterval ";
466
				$rrdcreate .= "DS:pfrate:GAUGE:$statesvalid:0:10000000 ";
467
				$rrdcreate .= "DS:pfstates:GAUGE:$statesvalid:0:10000000 ";
468
				$rrdcreate .= "DS:pfnat:GAUGE:$statesvalid:0:10000000 ";
469
				$rrdcreate .= "DS:srcip:GAUGE:$statesvalid:0:10000000 ";
470
				$rrdcreate .= "DS:dstip:GAUGE:$statesvalid:0:10000000 ";
471
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
472
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
473
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
474
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
475

    
476
				create_new_rrd($rrdcreate);
477
			}
478

    
479
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
480
			if($g['booting']) {
481
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
482
			}
483

    
484
 			/* the pf states gathering function. */
485
 			$rrdupdatesh .= "\n";
486
			$rrdupdatesh .= "pfctl_si_out=\"` $pfctl -si > /tmp/pfctl_si_out `\"\n";
487
			$rrdupdatesh .= "pfctl_ss_out=\"` $pfctl -ss > /tmp/pfctl_ss_out`\"\n";
488
			$rrdupdatesh .= "pfrate=\"` cat /tmp/pfctl_si_out | egrep \"inserts|removals\" | awk '{ pfrate = \$3 + pfrate } {print pfrate}'|tail -1 `\"\n";
489
 			$rrdupdatesh .= "pfstates=\"` cat /tmp/pfctl_ss_out | egrep -v \"<\\-.*?<\\-|\\->.*?\\->\" | wc -l|sed 's/ //g'`\"\n";
490
			$rrdupdatesh .= "pfnat=\"` cat /tmp/pfctl_ss_out | egrep '<\\-.*?<\\-|\\->.*?\\->' | wc -l|sed 's/ //g' `\"\n";
491
 			$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";
492
 			$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";
493
			$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$states N:\$pfrate:\$pfstates:\$pfnat:\$srcip:\$dstip\n\n";
494

    
495
			/* End pf states statistics */
496

    
497
			/* CPU, create CPU statistics database */
498
			if(! file_exists("$rrddbpath$ifname$proc")) {
499
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$proc --step $rrdprocinterval ";
500
				$rrdcreate .= "DS:user:GAUGE:$procvalid:0:10000000 ";
501
				$rrdcreate .= "DS:nice:GAUGE:$procvalid:0:10000000 ";
502
				$rrdcreate .= "DS:system:GAUGE:$procvalid:0:10000000 ";
503
				$rrdcreate .= "DS:interrupt:GAUGE:$procvalid:0:10000000 ";
504
				$rrdcreate .= "DS:processes:GAUGE:$procvalid:0:10000000 ";
505
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
506
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
507
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
508
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
509

    
510
				create_new_rrd($rrdcreate);
511
			}
512

    
513
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
514
			if($g['booting']) {
515
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
516
			}
517

    
518
 			/* the CPU stats gathering function. */
519
 			$rrdupdatesh .= "`$top -d 2 -s 1 0 | $awk '{gsub(/%/, \"\")} BEGIN { \\\n";
520
			$rrdupdatesh .= "printf \"$rrdtool update $rrddbpath$ifname$proc \" } \\\n";
521
			$rrdupdatesh .= "{ if ( \$2 == \"processes:\" ) { processes = \$1; } \\\n";
522
			$rrdupdatesh .= "else if ( \$1 == \"CPU:\" ) { user = \$2; nice = \$4; sys = \$6; interrupt = \$8; } \\\n";
523
			$rrdupdatesh .= "} END { printf \"N:\"user\":\"nice\":\"sys\":\"interrupt\":\"processes }'`\n\n";
524

    
525
			/* End CPU statistics */
526

    
527
			/* Memory, create Memory statistics database */
528
			if(! file_exists("$rrddbpath$ifname$mem")) {
529
				$rrdcreate = "$rrdtool create $rrddbpath$ifname$mem --step $rrdmeminterval ";
530
				$rrdcreate .= "DS:active:GAUGE:$memvalid:0:10000000 ";
531
				$rrdcreate .= "DS:inactive:GAUGE:$memvalid:0:10000000 ";
532
				$rrdcreate .= "DS:free:GAUGE:$memvalid:0:10000000 ";
533
				$rrdcreate .= "DS:cache:GAUGE:$memvalid:0:10000000 ";
534
				$rrdcreate .= "DS:wire:GAUGE:$memvalid:0:10000000 ";
535
				$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
536
				$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
537
				$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
538
				$rrdcreate .= "RRA:MIN:0.5:720:3000 ";
539
				$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
540
				$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
541
				$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
542
				$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
543
				$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
544
				$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
545
				$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
546
				$rrdcreate .= "RRA:MAX:0.5:720:3000";
547

    
548
				create_new_rrd($rrdcreate);
549
			}
550

    
551
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
552
			if($g['booting']) {
553
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
554
			}
555

    
556
 			/* the Memory stats gathering function. */
557
 			$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 | ";
558
			$rrdupdatesh .= " $awk '{getline active;getline inactive;getline free;getline cache;getline wire;printf \"$rrdtool update $rrddbpath$ifname$mem N:\"";
559
			$rrdupdatesh .= "((active/$0) * 100)\":\"((inactive/$0) * 100)\":\"((free/$0) * 100)\":\"((cache/$0) * 100)\":\"(wire/$0 * 100)}'`\n\n";
560
			
561
			/* End Memory statistics */
562

    
563
			/* SPAMD, set up the spamd rrd file */
564
			if (isset($config['installedpackages']['spamdsettings']) &&
565
				 isset ($config['installedpackages']['spamdsettings']['config'][0]['enablerrd'])) {
566
				/* set up the spamd rrd file */
567
				if (!file_exists("$rrddbpath$ifname$spamd")) {
568
					$rrdcreate = "$rrdtool create $rrddbpath$ifname$spamd --step $rrdspamdinterval ";
569
					$rrdcreate .= "DS:conn:GAUGE:$spamdvalid:0:10000 ";
570
					$rrdcreate .= "DS:time:GAUGE:$spamdvalid:0:86400 ";
571
					$rrdcreate .= "RRA:MIN:0.5:1:1000 ";
572
					$rrdcreate .= "RRA:MIN:0.5:5:1000 ";
573
					$rrdcreate .= "RRA:MIN:0.5:60:1000 ";
574
					$rrdcreate .= "RRA:MIN:0.5:720:3000 ";
575
					$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
576
					$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
577
					$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
578
					$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
579
					$rrdcreate .= "RRA:MAX:0.5:1:1000 ";
580
					$rrdcreate .= "RRA:MAX:0.5:5:1000 ";
581
					$rrdcreate .= "RRA:MAX:0.5:60:1000 ";
582
					$rrdcreate .= "RRA:MAX:0.5:720:3000 ";
583

    
584
					create_new_rrd($rrdcreate);
585
				}
586

    
587
				$rrdupdatesh .= "\n";
588
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
589
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
590
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
591

    
592
			}
593
		/* End System statistics */
594

    
595
		$rrdupdatesh .= "sleep 60\n";
596
		$rrdupdatesh .= "done\n";
597
		log_error("Creating rrd update script");
598
		/* write the rrd update script */
599
		$updaterrdscript = "{$g['vardb_path']}/rrd/updaterrd.sh";
600
		$fd = fopen("$updaterrdscript", "w");
601
		fwrite($fd, "$rrdupdatesh");
602
		fclose($fd);
603

    
604
		/* kill off traffic collectors */
605
		kill_traffic_collector();
606

    
607
		/* start traffic collector */
608
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
609

    
610
	} else {
611
		/* kill off traffic collectors */
612
		kill_traffic_collector();
613
	}
614

    
615
	if($g['booting']) 
616
		echo "done.\n";
617
		
618
}
619

    
620
function kill_traffic_collector() {
621
	mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
622
}
623

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

    
759
?>
(34-34/50)