Project

General

Profile

Download (28.1 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
/* include all configuration functions */
31
require_once("functions.inc");
32
require_once("pkg-utils.inc");
33
require_once("notices.inc");
34
require_once("globals.inc");
35

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

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

    
49
function create_new_rrd($rrdcreatecmd) {
50
	$rrdcreateoutput = array();
51
	$rrdcreatereturn = 0;
52

    
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
	$numrraold = count($rrdoldxml['rra']);
63
	$numdsold = count($rrdoldxml['ds']);
64
	$numrranew = count($rrdnewxml['rra']);
65
	$numdsnew = count($rrdnewxml['ds']);
66
	log_error("Import RRD has $numdsold DS values and $numrraold RRA databases, new format RRD has $numdsnew DS values and $numrranew RRA databases");
67
	
68
	/* add data sources not found in the old array from the new array */
69
	$i = 0;
70
	foreach($rrdnewxml['ds'] as $ds) {
71
		if(!is_array($rrdoldxml['ds'][$i])) {
72
			$rrdoldxml['ds'][$i] = $rrdnewxml['ds'][$i];
73
			/* set unknown values to 0 */
74
			$rrdoldxml['ds'][$i]['last_ds'] = " 0.0000000000e+00 ";
75
			$rrdoldxml['ds'][$i]['value'] = " 0.0000000000e+00 ";
76
			$rrdoldxml['ds'][$i]['unknown_sec'] = "0";
77
		}
78
		$i++;
79
	}
80

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

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

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

    
148
	$numrranew = count($rrdoldxml['rra']);
149
	$numdsnew = count($rrdoldxml['ds']);
150
	log_error("The new RRD now has $numdsnew DS values and $numrranew RRA databases");
151
	return $rrdoldxml;
152
}
153

    
154
function enable_rrd_graphing() {
155
	global $config, $g, $altq_list_queues;
156

    
157
	if($g['booting']) 
158
		echo "Generating RRD graphs...";
159

    
160
	$rrddbpath = "/var/db/rrd/";
161
	$rrdgraphpath = "/usr/local/www/rrd";
162

    
163
	$traffic = "-traffic.rrd";
164
	$packets = "-packets.rrd";
165
	$states = "-states.rrd";
166
	$wireless = "-wireless.rrd";
167
	$queues = "-queues.rrd";
168
	$queuesdrop = "-queuedrops.rrd";
169
	$spamd = "-spamd.rrd";
170
	$proc = "-processor.rrd";
171
	$mem = "-memory.rrd";
172

    
173
	$rrdtool = "/usr/bin/nice -n20 /usr/local/bin/rrdtool";
174
	$netstat = "/usr/bin/netstat";
175
	$awk = "/usr/bin/awk";
176
	$tar = "/usr/bin/tar";
177
	$pfctl = "/sbin/pfctl";
178
	$sysctl = "/sbin/sysctl";
179
	$php = "/usr/local/bin/php";
180
	$top = "/usr/bin/top";
181
	$spamd_gather = "/usr/local/bin/spamd_gather_stats.php";
182
	$ifconfig = "/sbin/ifconfig";
183

    
184
	$rrdtrafficinterval = 60;
185
	$rrdwirelessinterval = 60;
186
	$rrdqueuesinterval = 60;
187
	$rrdqueuesdropinterval = 60;
188
	$rrdpacketsinterval = 60;
189
	$rrdstatesinterval = 60;
190
	$rrdspamdinterval = 60;
191
	$rrdlbpoolinterval = 60;
192
	$rrdprocinterval = 60;
193
	$rrdmeminterval = 60;
194

    
195
	$trafficvalid = $rrdtrafficinterval * 2;
196
	$wirelessvalid = $rrdwirelessinterval * 2;
197
	$queuesvalid = $rrdqueuesinterval * 2;
198
	$queuesdropvalid = $rrdqueuesdropinterval * 2;
199
	$packetsvalid = $rrdpacketsinterval * 2;
200
	$statesvalid = $rrdstatesinterval*2;
201
	$spamdvalid = $rrdspamdinterval * 2;
202
	$lbpoolvalid = $rrdlbpoolinterval * 2;
203
	$procvalid = $rrdlbpoolinterval * 2;
204
	$memvalid = $rrdmeminterval * 2;
205

    
206
	/* Asume GigE for now */
207
	$downstream = 125000000;
208
	$upstream = 125000000;
209

    
210
	/* read the shaper config */
211
	read_altq_config();
212

    
213
	$rrdrestore = "";
214
	$rrdreturn = "";
215

    
216
	if (isset ($config['rrd']['enable'])) {
217

    
218
		/* create directory if needed */
219
		if (!is_dir("$rrddbpath")) {
220
			mkdir("$rrddbpath", 0755);
221
		}
222

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

    
236
		/* db update script */
237
		$rrdupdatesh = "#!/bin/sh\n";
238
		$rrdupdatesh .= "\n";
239
		$rrdupdatesh .= "counter=1\n";
240
		$rrdupdatesh .= "while [ \"\$counter\" -ne 0 ]\n";
241
		$rrdupdatesh .= "do\n";
242
		$rrdupdatesh .= "";
243

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

    
254
		foreach ($ifdescrs as $realif => $ifdescr) {
255
			$ifname = $ifdescr['friendly'];
256
			$state = $ifdescr['up'];
257

    
258
			/* skip interfaces that do not have a friendly name */
259
			if ("$ifname" == "") {
260
				continue;
261
			}
262

    
263
			/* or are down */
264
			if (!$state) {
265
				continue;
266
			}
267

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

    
280
				create_new_rrd($rrdcreate);
281
			}
282

    
283
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
284
			if($g['booting']) {
285
				exec("$rrdtool update $rrddbpath$ifname$traffic N:U:U:U:U");
286
			}
287

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

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

    
306
				create_new_rrd($rrdcreate);
307
			}
308

    
309
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
310
			if($g['booting']) {
311
				exec("$rrdtool update $rrddbpath$ifname$packets N:U:U:U:U");
312
			}
313

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

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

    
335
				/* enter UNKNOWN values in the RRD so it knows we rebooted. */
336
				if($g['booting']) {
337
					exec("$rrdtool update $rrddbpath$ifname$wireless N:U:U:U");
338
				}
339

    
340
				$rrdupdatesh .= "\n";
341
				$rrdupdatesh .= "# polling wireless for interface $ifname $realif \n";
342
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$wireless N:\\\n";
343
				$rrdupdatesh .= "`$ifconfig {$realif} list ap| $awk 'gsub(\"M\", \"\") {getline 2;print substr(\$5, 0, length(\$5)-2) \":\" $4 \":\" $3}'`\n";
344
			}
345

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

    
377
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
378
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
379
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
380
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
381

    
382
						create_new_rrd($rrdcreate);
383
					}
384

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

    
393
						$rrdcreate .= "RRA:AVERAGE:0.5:1:1000 ";
394
						$rrdcreate .= "RRA:AVERAGE:0.5:5:1000 ";
395
						$rrdcreate .= "RRA:AVERAGE:0.5:60:1000 ";
396
						$rrdcreate .= "RRA:AVERAGE:0.5:720:3000 ";
397

    
398
						create_new_rrd($rrdcreate);
399
					}
400

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

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

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

    
455
		/* System only statistics */
456
		$ifname = "system";
457

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

    
471
				create_new_rrd($rrdcreate);
472
			}
473

    
474
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
475
			if($g['booting']) {
476
				exec("$rrdtool update $rrddbpath$ifname$states N:U:U:U:U:U");
477
			}
478

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

    
490
			/* End pf states statistics */
491

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

    
505
				create_new_rrd($rrdcreate);
506
			}
507

    
508
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
509
			if($g['booting']) {
510
				exec("$rrdtool update $rrddbpath$ifname$proc N:U:U:U:U:U");
511
			}
512

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

    
520
			/* End CPU statistics */
521

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

    
543
				create_new_rrd($rrdcreate);
544
			}
545

    
546
			/* enter UNKNOWN values in the RRD so it knows we rebooted. */
547
			if($g['booting']) {
548
				exec("$rrdtool update $rrddbpath$ifname$mem N:U:U:U:U:U");
549
			}
550

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

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

    
579
					create_new_rrd($rrdcreate);
580
				}
581

    
582
				$rrdupdatesh .= "\n";
583
				$rrdupdatesh .= "# polling spamd for connections and tarpitness \n";
584
				$rrdupdatesh .= "$rrdtool update $rrddbpath$ifname$spamd \\\n";
585
				$rrdupdatesh .= "`$php -q $spamd_gather`\n";
586

    
587
			}
588
		/* End System statistics */
589

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

    
599
		/* kill off traffic collectors */
600
		kill_traffic_collector();
601

    
602
		/* start traffic collector */
603
		mwexec_bg("/usr/bin/nice -n20 /bin/sh $updaterrdscript");
604

    
605
	} else {
606
		/* kill off traffic collectors */
607
		kill_traffic_collector();
608
	}
609

    
610
	if($g['booting']) 
611
		echo "done.\n";
612
		
613
}
614

    
615
function kill_traffic_collector() {
616
	mwexec("ps awwwux | grep '/[u]pdaterrd.sh' | awk '{print $2}' | xargs kill");
617
}
618

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

    
754
?>
(27-27/40)