Subversion Repositories ALCASAR

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
1154 crox53 1
#!/usr/bin/perl
2
#
3
#  Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
4
#  All rights reserved.
5
#
6
#  Redistribution and use in source and binary forms, with or without
7
#  modification, are permitted provided that the following conditions are met:
8
#
9
#   * Redistributions of source code must retain the above copyright notice,
10
#	 this list of conditions and the following disclaimer.
11
#   * Redistributions in binary form must reproduce the above copyright notice,
12
#	 this list of conditions and the following disclaimer in the documentation
13
#	 and/or other materials provided with the distribution.
14
#   * Neither the name of SWITCH nor the names of its contributors may be
15
#	 used to endorse or promote products derived from this software without
16
#	 specific prior written permission.
17
#
18
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
#  POSSIBILITY OF SUCH DAMAGE.
29
#
30
#  $Author: peter $
31
#
32
#  $Id: PortTracker.pm 27 2011-12-29 12:53:29Z peter $
33
#
34
#  $LastChangedRevision: 27 $
35
 
36
# Demo plugin for NfSen
37
#
38
# This plugin demonstrates the use of plugins
39
 
40
package PortTracker;
41
 
42
use strict;
43
use NfSen;
44
use NfConf;
45
 
46
#
47
# The plugin may send any messages to syslog
48
# Do not initialize syslog, as this is done by 
49
# the main process nfsen-run
50
use Sys::Syslog;
51
 
52
our $VERSION = 130;
53
 
54
our %cmd_lookup = (
55
	'get-portgraph'	=> \&GetPortGraph,
56
	'get-topN'	 	=> \&GetTopN,
57
);
58
 
59
my ( $nftrack, $PROFILEDATADIR );
60
 
61
my $PORTSDBDIR = "/var/log/netflow/porttracker";
62
 
63
my $EODATA  = ".\n";
64
 
65
# colours used in graphs
66
# if more than 12 graphs are drawn ( does this really make sense ? ) 
67
# the same colours are used again
68
my @colour = ( 
69
	'#ff0000', '#ff8000', '#ffff00', '#80ff00', '#00ff00',
70
	'#00ff80', '#00ffff', '#0080ff', '#0000ff', '#8000ff',
71
	'#ff00ff', '#ff0080'
72
);
73
 
74
 
75
sub GetTopN {
76
    my $socket  = shift;
77
    my $opts    = shift;
78
 
79
	my $interval;
80
	if ( !exists $$opts{'interval'} ) {
81
		$interval = 1;
82
	} else {
83
		$interval = $$opts{'interval'};
84
	}
85
	print $socket ".Get topN ports\n";
86
 
87
	my $statfile = $interval == 24 ? 'portstat24.txt' : 'portstat.txt';
88
	print $socket ".topN ports $PORTSDBDIR/$statfile\n";
89
	if ( !open STAT, "$PORTSDBDIR/$statfile" ) {
90
		print $socket $EODATA;
91
		print $socket "ERR Open statfile '$PORTSDBDIR/$statfile': $!\n";
92
		return;
93
	}
94
 
95
	print $socket ".topN read ports\n";
96
	while ( <STAT> ) {
97
		chomp;
98
		print $socket "_topN=$_\n";
99
	}
100
	print $socket $EODATA;
101
	print $socket "OK Command completed\n",
102
 
103
} # End of GetPortGraph
104
 
105
sub GetPortGraph {
106
    my $socket  = shift;
107
    my $opts    = shift;
108
 
109
	# get all arguments:
110
	# Example:
111
	# proto typw  logscale light tstart     tend       topN              track_list
112
	# tcp   flows 0        0     1116495000 1116581400 '22 445 135 1433' '80 143'
113
	if ( !exists $$opts{'arg'} ) {
114
		print $socket $EODATA;
115
		print $socket "ERR Missing Arguments.\n";
116
	}
117
	my $ARGS = $$opts{'arg'};
118
	my $proto 		= shift @$ARGS;	# 'tcp' or 'udp'
119
	my $type  		= shift @$ARGS;	# 'flows', 'packets' or 'bytes'
120
	my $logscale	= shift @$ARGS;	# 0 or 1
121
	my $stacked		= shift @$ARGS;	# 0 or 1
122
	my $light 		= shift @$ARGS;	# 0 or 1
123
	my $tstart		= shift @$ARGS;	# start time - UNIX format
124
	my $tend		= shift @$ARGS;	# end time - UNIX format
125
	my $topN		= shift @$ARGS;	# TopN port list: string: ' ' separated port list
126
	my $track_list	= shift @$ARGS;	# Static track port list: string: ' ' separated port list
127
	my $skip_list	= shift @$ARGS;	# Static skip port list: string: ' ' separated port list
128
 
129
	if ( !defined $proto || !defined $type || !defined $logscale || !defined $stacked ||
130
		 !defined $light || !defined $tstart || !defined $tend || !defined $topN || 
131
		 !defined $track_list || !defined $skip_list ) {
132
		print $socket $EODATA;
133
		print $socket "ERR Argument Error.\n";
134
		return;
135
	}
136
	my @skipPorts = split '-', $skip_list;
137
 
138
	my @topN = split '-', $topN;
139
	my @track_list = split '-', $track_list;
140
 
141
	# remove the common ports in both lists from the dynamic topN list
142
	my %_tmp;
143
	@_tmp{@track_list} = @track_list;
144
	delete @_tmp{@topN};
145
	@track_list = sort keys %_tmp;
146
 
147
	# %_tmp = ();
148
	# @_tmp{@topN} = @topN;
149
	# delete @_tmp{@skipPorts};
150
	# @topN = keys %_tmp;
151
 
152
	%_tmp = ();
153
	my @_tmp;
154
	@_tmp{@skipPorts} = @skipPorts;
155
	foreach my $port ( @topN ) {
156
		push @_tmp, $port unless exists $_tmp{$port};
157
	}
158
	@topN = @_tmp;
159
 
160
	my $datestr = scalar localtime($tstart) . " - " . scalar localtime($tend);
161
	my $title   = uc($proto) . " " . ucfirst($type);
162
 
163
	my @DEFS = ();
164
 
165
	# Compile rrd args
166
	my @rrdargs = ();
167
	push @rrdargs, "-";	# output graphics to stdout
168
 
169
	foreach my $port ( @topN, @track_list ) {
170
		# assemble filename
171
		my $fileident = $port >> 10;
172
		my $rrdfile	= "$PORTSDBDIR/${proto}-${type}-$fileident.rrd";
173
		# which ident in this rrd file
174
		my $ident	=  $port & 1023;	# 0x0000001111111111 mask
175
		push @rrdargs, "DEF:Port${port}=$rrdfile:p${ident}:AVERAGE";
176
	}
177
 
178
	push @rrdargs, "--start",  "$tstart";
179
	push @rrdargs, "--end",    "$tend";
180
	push @rrdargs, "--title",  "$datestr - $title" unless $light;
181
	push @rrdargs, "--vertical-label", "$title"  unless $light;
182
 
183
	# lin or log graph?
184
	push @rrdargs, "--logarithmic" if $logscale;
185
 
186
	if ( $light ) {
187
		push @rrdargs, "-w";
188
		push @rrdargs, "288";
189
		push @rrdargs, "-h";
190
		push @rrdargs, "150";
191
		push @rrdargs, "--no-legend";	# no legend in small pictures
192
	} else {
193
		push @rrdargs, "-w";
194
		push @rrdargs, "576";
195
		push @rrdargs, "-h";
196
		push @rrdargs, "300";
197
	}
198
 
199
 
200
	my $i=0;
201
	my $area_set = 0;
202
	my $n = scalar @topN;
203
	push @rrdargs, "COMMENT:Top $n Ports\\n";
204
	if ( $stacked && scalar @topN ) {
205
		my $port = shift @topN;
206
		push @rrdargs, "AREA:Port${port}$colour[$i]:Port ${port}";
207
		$i++;
208
		$area_set = 1;
209
		foreach my $port ( @topN ) {
210
	 		push @rrdargs, "STACK:Port${port}$colour[$i]:Port ${port}";
211
	 		$i++;
212
		}
213
 
214
	} else {
215
		foreach my $port ( @topN ) {
216
			push @rrdargs, "LINE1:Port${port}$colour[$i]:Port ${port}";
217
			$i++;
218
		}
219
	}
220
 
221
	if ( scalar @track_list) {
222
		push @rrdargs, "COMMENT:\\n";
223
		push @rrdargs, "COMMENT:\\n";
224
		push @rrdargs, "COMMENT:Tracked Ports\\n";
225
	}
226
	if ( $stacked && scalar @track_list) {
227
		if ( !$area_set ) {
228
			my $port = shift @track_list;
229
			push @rrdargs, "AREA:Port${port}$colour[$i]:Port ${port}";
230
			$i++;
231
		}
232
		foreach my $port ( @track_list ) {
233
			push @rrdargs, "STACK:Port${port}$colour[$i]:Port ${port}";
234
			$i++;
235
		}
236
 
237
	} else {
238
		foreach my $port ( @track_list ) {
239
			push @rrdargs, "LINE2:Port${port}$colour[$i]:Port ${port}";
240
			$i++;
241
		}
242
	}
243
	if ( scalar @skipPorts) {
244
		push @rrdargs, "COMMENT:\\n";
245
		push @rrdargs, "COMMENT:\\n";
246
		my $portlist = join ',', @skipPorts;
247
		push @rrdargs, "COMMENT:Skipped Ports $portlist\\n";
248
	}
249
	my ($averages,$xsize,$ysize) = RRDs::graph( @rrdargs );
250
 
251
	if (my $ERROR = RRDs::error) {
252
		print "ERROR: $ERROR\n";
253
	} 
254
 
255
} # End of GenPortGraph
256
 
257
 
258
sub nftrack_execute {
259
	my $command = shift;
260
 
261
	syslog('debug', $command);
262
 
263
	my $ret = system($command);
264
	if ( $ret == - 1 ) {
265
		syslog('err', "Failed to execute nftrack: $!\n");
266
	} elsif ($ret & 127) {
267
		syslog('err', "nftrack died with signal %d, %s coredump\n", ($ret & 127),  ($ret & 128) ? 'with' : 'without');
268
	} else {
269
		syslog('debug', "nftrack exited with value %d\n", $ret >> 8);
270
	}
271
 
272
} # End of nftrack_execute
273
 
274
#
275
# Periodic function
276
#   input:  hash reference including the items:
277
#           'profile'       profile name
278
#           'profilegroup'  profile group
279
#           'timeslot'      time of slot to process: Format yyyymmddHHMM e.g. 200503031200
280
sub run {
281
    my $argref       = shift;
282
 
283
    my $profile      = $$argref{'profile'};
284
    my $profilegroup = $$argref{'profilegroup'};
285
    my $timeslot     = $$argref{'timeslot'};
286
 
287
	syslog('debug', "PortTracker run: Profile: $profile, Time: $timeslot");
288
 
289
	my %profileinfo	 = NfProfile::ReadProfile($profile);
290
	my $netflow_sources = "$PROFILEDATADIR/$profile/$profileinfo{'sourcelist'}";
291
 
292
	# 
293
	# process all sources of this profile at once
294
	my $command = "$nftrack -L $NfConf::syslog_facility -M $netflow_sources -r nfcapd.$timeslot -d $PORTSDBDIR -A -t $timeslot -s -p -w $PORTSDBDIR/portstat.txt";
295
	nftrack_execute($command);
296
 
297
	$command = "$nftrack -d $PORTSDBDIR -S -p -w $PORTSDBDIR/portstat24.txt";
298
	nftrack_execute($command);
299
 
300
	#
301
	# Process the output and notify the duty team
302
 
303
	syslog('debug', "PortTracker run: Done.");
304
 
305
} # End of run
306
 
307
sub Init {
308
	syslog("info", "PortTracker: Init");
309
 
310
	# Init some vars
311
	$nftrack  = "$NfConf::PREFIX/nftrack";
312
	$PROFILEDATADIR = "$NfConf::PROFILEDATADIR";
313
 
314
	return 1;
315
}
316
 
317
sub Cleanup {
318
	syslog("info", "PortTracker Cleanup");
319
	# not used here
320
}
321
 
322
1;