1#!/usr/local/bin/perl
2#
3#  Purpose:
4#  FlowViewer_Main.cgi permits a Web user to analyze Net Flow data stored
5#  in flow tools format and create an HTML report.
6#
7#  Description:
8#  The script responds to an HTML form from the user in order to collect
9#  parameters that will control the analysis (e.g., router, time-period, ip
10#  addresses etc.) Upon receipt of the form input the script creates a flow tools
11#  filter file which controls the selection of the data via the invocation of
12#  additional flow tools utilities. An HTML report is then generated.
13#
14#  Input arguments (received from the form):
15#  Name                 Description
16#  -----------------------------------------------------------------------
17#  device_name          An identifying name of the device (e.g. router1)
18#  flow_select          Identifies which flows to include wrt time period
19#  start_date           Start date of analysis period
20#  start_time           Start time of analysis period
21#  end_date             End date of analysis period
22#  end_time             End time of analysis period
23#  source_addresses     Constrain flows examined to these source IP addresses
24#  source_ports         Constrain flows examined to these source ports
25#  source_ifs           Constrain flows examined to these input interfaces
26#  sif_names            Constrain flows examined to these named interfaces
27#  source_ases          Constrain flows examined to these source ASes
28#  dest_addresses       Constrain flows examined to these dest. IP addresses
29#  dest_ports           Constrain flows examined to these dest. ports
30#  dest_ifs             Constrain flows examined to these output interfaces
31#  dif_names            Constrain flows examined to these named interfaces
32#  dest_ases            Constrain flows examined to these dest. ASes
33#  tos_fields           Constrain flows examined by specified TOS field values
34#  tcp_flags            Constrain flows examined by specified TCP flag values
35#  exporter             Constrain flows examined to specified exporter IP address
36#  nexthop_ips          Constrain flows examined to specified Next Hop IP address
37#  protocols            Constrain flows examined to these protocols
38#  print_report         Select from these various report options
39#  stat_report          Select from these various statistics options
40#  cutoff_lines         Number of report lines to print out
41#  cutoff_octets        Minimum number of octets for inclusion in report
42#  sort_field           Sorts on (Octets, Flows, Packets) for first report
43#  resolve_addresses    Whether or not to resolve IP addresses
44#  unit_conversion      Whether or not to convert octets to GB, KB, etc.
45#  sampling_multiplier  Value to multiply flow data (for sampled routers)
46#  pie_charts           Generate pie charts; optional 'others' category
47#
48#  Notes:
49#  1. It is a good idea to retain the host_names GDBM file (names), even if it
50#     gets large, since it is up to 1000 times faster than using 'dig'.
51#
52#  Modification history:
53#  Author       Date            Vers.   Description
54#  -----------------------------------------------------------------------
55#  J. Loiacono  07/04/2005      1.0     Original version.
56#  J. Loiacono  01/01/2006      2.0     FlowGrapher, new functions, speed
57#  J. Loiacono  01/16/2006      2.1     Fixed compute of concatenation date
58#  J. Loiacono  01/26/2006      2.2     New flow_select option for inclusion
59#  J. Loiacono  07/04/2006      3.0     Renamed for re-organization
60#                                       Single script for GDBM/NDBM (thanks Ed Ravin)
61#  J. Loiacono  12/25/2006      3.1     [No Change to this module]
62#  J. Loiacono  02/14/2007      3.2     [No Change to this module]
63#  J. Loiacono  12/07/2007      3.3     Sampling Multiplier, Pie Charts
64#                                       AS resolving (thanks Sean Cardus)
65#                                       Named IFs, Unit Conv. (thanks C. Kishimoto)
66#  J. Loiacono  12/15/2007      3.3.1   New $no_devices ... parameter
67#  J. Loiacono  03/17/2011      3.4     Support for change of device w/o reset
68#                                       Support for meaningful Save report names
69#                                       Concatenation now includes 'temp' files
70#                                       Dynamic Resolved column width, flows/sec
71#  J. Loiacono  05/08/2012      4.0     Major upgrade for IPFIX/v9 using SiLK,
72#                                       New User Interface
73#  J. Loiacono  04/15/2013      4.1     Removed extraneuos formatting
74#  J. Loiacono  09/11/2013      4.2.1   Mods for international date formatting
75#  J. Loiacono  01/26/2014      4.3     Introduced Detect Scanning
76#  J. Loiacono  07/04/2014      4.4     Multiple dashboards and flow analysis
77#  J. Loiacono  11/02/2014      4.5     SiLK local timezone fixes
78#                                       Cleaned up checking of entered times
79#                                       Extended pie-charts to some Printed Reports
80#                                       Use of $site_config_file on SiLK commands
81#
82#$Author$
83#$Date$
84#$Header$
85#
86###########################################################################
87#
88#               BEGIN EXECUTABLE STATEMENTS
89#
90
91use FlowViewer_Configuration;
92use FlowViewer_Utilities;
93use FlowViewer_UI;
94use File::stat;
95
96if ($debug_viewer eq "Y") { open (DEBUG,">$work_directory/DEBUG_VIEWER"); }
97if ($debug_viewer eq "Y") { print DEBUG "In FlowViewer_Main.cgi\n"; }
98
99# Tie in the appropriate 'names' files which saves IP address resolved names
100
101if (eval 'local $SIG{"__DIE__"}= sub { }; use GDBM_File;
102	tie %host_names, "GDBM_File", "$names_directory/names",    GDBM_WRCREAT, 0666;' ) { print DEBUG "Using GDBM\n"; };
103if (eval 'local $SIG{"__DIE__"}= sub { }; use NDBM_File; use Fcntl;
104	tie %host_names, "GDBM_File", "$names_directory/names",    GDBM_WRCREAT, 0666;' ) { print DEBUG "Using NDBM\n"; };
105
106# Tie in the appropriate 'as_names' file which saves resolved AS names
107
108if (eval 'local $SIG{"__DIE__"}= sub { }; use GDBM_File;
109	tie %as_names,   "GDBM_File", "$names_directory/as_names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using GDBM\n"; };
110if (eval 'local $SIG{"__DIE__"}= sub { }; use NDBM_File; use Fcntl;
111	tie %as_names,   "GDBM_File", "$names_directory/as_names", GDBM_WRCREAT, 0666;' ) { print DEBUG "Using NDBM\n"; };
112
113if ((eval 'local $SIG{"__DIE__"}= sub { }; use GD; use GD::Graph::pie; use GD::Text') && ($pie_charts > 0)) {
114	if ($debug_viewer eq "Y") { print DEBUG "Using GD::Graph:Pie, etc.\n"; }
115}
116
117# Set up the Pie Chart colors
118
119GD::Graph::colour::read_rgb("FlowGrapher_Colors") or die "cannot read colors";
120
121# Retrieve the form inputs
122
123read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
124@pairs = split(/&/, $buffer);
125foreach $pair (@pairs) {
126    ($name, $value) = split(/=/, $pair);
127    $value =~ tr/+/ /;
128    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
129    $FORM{$name} = $value;
130}
131
132# Clean up input
133
134($fv_link,$FORM{device_name}) = split(/DDD/,$FORM{device_name});
135($fv_link,$FORM{exporter})    = split(/EEE/,$FORM{exporter});
136
137if ($debug_viewer eq "Y") { print DEBUG "FORM{device_name}: $FORM{device_name}\n"; }
138if ($debug_viewer eq "Y") { print DEBUG "FORM{exporter}: $FORM{exporter}\n"; }
139
140$FORM{source_address} =~ s/\s+//g; $FORM{source_address} =~ s/,/, /g;
141$FORM{source_port}    =~ s/\s+//g; $FORM{source_port}    =~ s/,/, /g;
142$FORM{source_if}      =~ s/\s+//g; $FORM{source_if}      =~ s/,/, /g;
143$FORM{source_as}      =~ s/\s+//g; $FORM{source_as}      =~ s/,/, /g;
144$FORM{dest_address}   =~ s/\s+//g; $FORM{dest_address}   =~ s/,/, /g;
145$FORM{dest_port}      =~ s/\s+//g; $FORM{dest_port}      =~ s/,/, /g;
146$FORM{dest_if}        =~ s/\s+//g; $FORM{dest_if}        =~ s/,/, /g;
147$FORM{dest_as}        =~ s/\s+//g; $FORM{dest_as}        =~ s/,/, /g;
148$FORM{protocols}      =~ s/\s+//g; $FORM{protocols}      =~ s/,/, /g;
149$FORM{tos_fields}     =~ s/\s+//g; $FORM{tos_fields}     =~ s/,/, /g;
150$FORM{tcp_flags}      =~ s/\s+//g; $FORM{tcp_flags}      =~ s/,/, /g;
151$FORM{nexthop_ip}     =~ s/\s+//g; $FORM{nexthop_ip}     =~ s/,/, /g;
152$FORM{sif_name}       =~ s/,/, /g;
153$FORM{dif_name}       =~ s/,/, /g;
154
155# Parameters for generating a FlowViewer report
156
157$active_dashboard    = $FORM{'active_dashboard'};
158$device_name         = $FORM{'device_name'};
159$flow_select         = $FORM{'flow_select'};
160$start_date          = $FORM{'start_date'};
161$start_time          = $FORM{'start_time'};
162$end_date            = $FORM{'end_date'};
163$end_time            = $FORM{'end_time'};
164$source_addresses    = $FORM{'source_address'};
165$source_ports        = $FORM{'source_port'};
166$source_ifs          = $FORM{'source_if'};
167$sif_names           = $FORM{'sif_name'};
168$source_ases         = $FORM{'source_as'};
169$dest_addresses      = $FORM{'dest_address'};
170$dest_ports          = $FORM{'dest_port'};
171$dest_ifs            = $FORM{'dest_if'};
172$dif_names           = $FORM{'dif_name'};
173$dest_ases           = $FORM{'dest_as'};
174$protocols           = $FORM{'protocols'};
175$tcp_flags           = $FORM{'tcp_flags'};
176$tos_fields          = $FORM{'tos_fields'};
177$exporter            = $FORM{'exporter'};
178$nexthop_ips         = $FORM{'nexthop_ip'};
179$print_report        = $FORM{'print_report'};
180$stat_report         = $FORM{'stat_report'};
181$cutoff_lines        = $FORM{'cutoff_lines'};
182$cutoff_octets       = $FORM{'cutoff_octets'};
183$sort_field          = $FORM{'sort_field'};
184$resolve_addresses   = $FORM{'resolve_addresses'};
185$unit_conversion     = $FORM{'unit_conversion'};
186$sampling_multiplier = $FORM{'sampling_multiplier'};
187$pie_charts          = $FORM{'pie_charts'};
188$flow_analysis       = $FORM{'flow_analysis'};
189$silk_rootdir        = $FORM{'silk_rootdir'};
190$silk_class          = $FORM{'silk_class'};
191$silk_flowtype       = $FORM{'silk_flowtype'};
192$silk_type           = $FORM{'silk_type'};
193$silk_sensors        = $FORM{'silk_sensors'};
194$silk_switches       = $FORM{'silk_switches'};
195
196if ($site_config_file ne "") { $site_config_modifier = "--site-config-file=$site_config_file "; }
197
198# Convert into US date format for internal processing
199
200if ($date_format eq "DMY") {
201        ($temp_day_s,$temp_mnth_s,$temp_yr_s) = split(/\//,$start_date);
202        ($temp_day_e,$temp_mnth_e,$temp_yr_e) = split(/\//,$end_date);
203} elsif ($date_format eq "DMY2") {
204        ($temp_day_s,$temp_mnth_s,$temp_yr_s) = split(/\./,$start_date);
205        ($temp_day_e,$temp_mnth_e,$temp_yr_e) = split(/\./,$end_date);
206} elsif ($date_format eq "YMD") {
207        ($temp_yr_s,$temp_mnth_s,$temp_day_s) = split(/\-/,$start_date);
208        ($temp_yr_e,$temp_mnth_e,$temp_day_e) = split(/\-/,$end_date);
209} else {
210        ($temp_mnth_s,$temp_day_s,$temp_yr_s) = split(/\//,$start_date);
211        ($temp_mnth_e,$temp_day_e,$temp_yr_e) = split(/\//,$end_date);
212}
213$start_date = $temp_mnth_s ."/". $temp_day_s ."/". $temp_yr_s;
214$end_date   = $temp_mnth_e ."/". $temp_day_e ."/". $temp_yr_e;
215
216if ($debug_viewer eq "Y") { print DEBUG "FORM{start_date}: $FORM{start_date}  start_date: $start_date  FORM{end_date}: $FORM{end_date}  end_date: $end_date\n"; }
217
218# Determine if we are looking at an IPFIX device
219
220$IPFIX = 0;
221foreach $ipfix_device (@ipfix_devices) {
222        if ($device_name eq $ipfix_device) { $IPFIX = 1; if ($debug_viewer eq "Y") { print DEBUG "This device is exporting IPFIX\n";} }
223}
224
225# Start up the Saved file
226
227$saved_suffix = &get_suffix;
228$saved_hash   = "FlowViewer_save_$saved_suffix";
229$filter_hash  = "FV_$saved_hash";
230$saved_html   = "$work_directory/$saved_hash";
231&start_saved_file($saved_html);
232
233# Start the FlowViewer Report web page output
234
235&create_UI_top($active_dashboard);
236&create_UI_service("FlowViewer_Main","service_top",$active_dashboard,$filter_hash);
237print " <div id=content_wide>\n";
238print " <span class=text16>FlowViewer Report from $device_name</span>\n";
239&create_filter_output("FlowViewer_Main",$filter_hash);
240
241if ($time_zone eq "") {
242        open(DATE,"date 2>&1|");
243        while (<DATE>) {
244                ($d_tz,$m_tz,$dt_tz,$t_tz,$time_zone,$y_tz) = split(/\s+/,$_);
245        }
246}
247
248# Check dates and times for input errors
249
250($mn,$da,$yr) = split(/\//,$start_date);
251if ( $mn=~/\D/ || $da=~/\D/ || $yr=~/\D/ ) { &print_error("Bad date format: $FORM{start_date}"); };
252if ( $mn<1 || $mn>12 || $da<1 || $da>31 || $yr<1990 || $yr>2100 ) { &print_error("Bad date format: $FORM{start_date}"); }
253if (length($mn) < 2) { $mn = "0" . $mn; }
254if (length($da) < 2) { $da = "0" . $da; }
255$start_ymd = $yr . $mn . $da;
256$start_yr = $yr; $start_mn = $mn; $start_da = $da;
257
258($hr,$mi,$sc) = split(/:/,$start_time);
259if ( $hr=~/\D/ || $mi=~/\D/ || $sc=~/\D/ ) { &print_error("Bad time format: $FORM{start_time}"); };
260if (length($hr)>2 || $hr>23 || length($mi)>2 || $mi>59 || length($sc)>2 || $sc>59 ) { &print_error("Bad time format: $FORM{start_time}"); }
261
262($mn,$da,$yr) = split(/\//,$end_date);
263if ( $mn=~/\D/ || $da=~/\D/ || $yr=~/\D/ ) { &print_error("Bad date format: $FORM{end_date}"); };
264if ( $mn<1 || $mn>12 || $da<1 || $da>31 || $yr<1990 || $yr>2100 ) { &print_error("Bad date format: $FORM{end_date}"); }
265if (length($mn) < 2) { $mn = "0" . $mn; }
266if (length($da) < 2) { $da = "0" . $da; }
267$end_ymd = $yr . $mn . $da;
268$end_yr = $yr; $end_mn = $mn; $end_da = $da;
269
270($hr,$mi,$sc) = split(/:/,$end_time);
271if ( $hr=~/\D/ || $mi=~/\D/ || $sc=~/\D/ ) { &print_error("Bad time format: $FORM{end_time}"); };
272if (length($hr)>2 || $hr>23 || length($mi)>2 || $mi>59 || length($sc)>2 || $sc>59 ) { &print_error("Bad time format: $FORM{end_time}"); }
273
274if (($no_devices_or_exporters eq "N") && (($device_name eq "") && ($exporter eq ""))) {
275        print "<br><b>Must select a device or an exporter. <p>Use the \"back\" key to save inputs</b><br>";
276        exit;
277}
278
279if (($stat_report == 0) && ($print_report == 0)) { &print_error("Must specify a report."); }
280if (($stat_report != 0) && ($print_report != 0)) { &print_error("Two reports selected. Please reset one."); }
281
282if (($stat_report == 10) && ($print_report ne "0")) {
283	$stat_report = 0;
284}
285
286# Retrieve current time to use as a file suffix to permit more than one user to generate reports
287
288($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime(time);
289$mnth++;
290$yr += 1900;
291if ((0 < $mnth) && ($mnth < 10)) { $mnth = "0" . $mnth; }
292if ((0 < $date) && ($date < 10)) { $date = "0" . $date; }
293if ((0 <= $hr)  && ($hr  < 10)) { $hr  = "0" . $hr; }
294if ((0 <= $min) && ($min < 10)) { $min = "0" . $min; }
295if ((0 <= $sec) && ($sec < 10)) { $sec = "0" . $sec; }
296$prefix = $yr . $mnth . $date ."_". $hr . $min . $sec;
297$suffix = $hr . $min . $sec;
298
299if ($IPFIX) {
300
301	# Obtain user requested start time in SiLK-storage time zone
302
303	($temp_hr_s,$temp_min_s,$temp_sec_s) = split(/:/,$start_time);
304	if ($silk_compiled_localtime eq "Y") {
305		$start_epoch = timelocal($temp_sec_s,$temp_min_s,$temp_hr_s,$temp_day_s,$temp_mnth_s-1,$temp_yr_s-1900);
306		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime($start_epoch);
307	} else {
308		$start_epoch = timegm($temp_sec_s,$temp_min_s,$temp_hr_s,$temp_day_s,$temp_mnth_s-1,$temp_yr_s-1900);
309		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = gmtime($start_epoch);
310	}
311	$yr += 1900; $mnth++;
312	if (length($mnth) < 2) { $mnth = "0" . $mnth; }
313	if (length($date) < 2) { $date = "0" . $date; }
314	if (length($hr)   < 2) { $hr   = "0" . $hr; }
315	if (length($min)  < 2) { $min  = "0" . $min; }
316	if (length($sec)  < 2) { $sec  = "0" . $sec; }
317	$silk_period_start = $yr ."/". $mnth ."/". $date .":". $hr .":". $min .":". $sec;
318
319	# Obtain user requested end time in SiLK-storage time zone
320
321	($temp_hr_e,$temp_min_e,$temp_sec_e) = split(/:/,$end_time);
322	if ($silk_compiled_localtime eq "Y") {
323		$end_epoch = timelocal($temp_sec_e,$temp_min_e,$temp_hr_e,$temp_day_e,$temp_mnth_e-1,$temp_yr_e-1900);
324		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime($end_epoch);
325	} else {
326		$end_epoch = timegm($temp_sec_e,$temp_min_e,$temp_hr_e,$temp_day_e,$temp_mnth_e-1,$temp_yr_e-1900);
327		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = gmtime($end_epoch);
328	}
329	$yr += 1900; $mnth++;
330	if (length($mnth) < 2) { $mnth = "0" . $mnth; }
331	if (length($date) < 2) { $date = "0" . $date; }
332	if (length($hr)   < 2) { $hr   = "0" . $hr; }
333	if (length($min)  < 2) { $min  = "0" . $min; }
334	if (length($sec)  < 2) { $sec  = "0" . $sec; }
335	$silk_period_end = $yr ."/". $mnth ."/". $date .":". $hr .":". $min .":". $sec;
336
337} else {
338
339	# Determine flow-tools concatenation start and end times
340
341	$start_epoch     = date_to_epoch($start_date,$start_time,"LOCAL");
342	$end_epoch       = date_to_epoch($end_date,$end_time,"LOCAL");
343
344	$start_flows     = &flow_date_time($start_epoch,"LOCAL");
345	$end_flows       = &flow_date_time($end_epoch,"LOCAL");
346
347	$cat_start_epoch = $start_epoch - $flow_file_length - 1;
348	$cat_end_epoch   = $end_epoch   + $flow_capture_interval + 1;
349	$cat_start       = epoch_to_date($cat_start_epoch,"LOCAL");
350	$cat_end         = epoch_to_date($cat_end_epoch,"LOCAL");
351
352	$concatenate_parameters = "-a -t \"$cat_start\" -T \"$cat_end\" ";
353}
354
355$report_length = $end_epoch - $start_epoch;
356if ($report_length <= 0) { &print_error("End time ($end_date $end_time) earlier than Start time ($start_date $start_time)"); }
357
358if (!$IPFIX) {
359
360	if (($start_ymd ne $end_ymd) && ($end_epoch > $start_epoch)) {
361	        for ($i=0;$i<$maximum_days;$i++) {
362	                if (($cat_start_epoch + $i*86400) > $cat_end_epoch + 86400) { last; }
363	                ($sec,$min,$hr,$cat_date,$cat_mnth,$cat_yr,$day,$yr_date,$DST) = localtime($cat_start_epoch + $i*86400);
364	                $cat_mnth++;
365	                $cat_yr += 1900;
366	                if ((0 < $cat_mnth) && ($cat_mnth < 10)) { $cat_mnth = "0" . $cat_mnth; }
367	                if ((0 < $cat_date) && ($cat_date < 10)) { $cat_date = "0" . $cat_date; }
368
369			if ($exporter ne "") {
370	                	$cat_directory = "$exporter_directory";
371			} else {
372	                	$cat_directory = "$flow_data_directory/$device_name";
373			}
374
375			if ($N == -3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
376			if ($N == -2) { $cat_directory .= "/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
377			if ($N == -1) { $cat_directory .= "/$cat_yr\-$cat_mnth\-$cat_date"; }
378			if ($N == 1)  { $cat_directory .= "/$cat_yr"; }
379			if ($N == 2)  { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth"; }
380			if ($N == 3)  { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
381
382                        if (-e $cat_directory) { $concatenate_parameters .= "$cat_directory "; }
383
384			if ($N == 0)  { last; }
385	        }
386
387	} elsif ($start_ymd eq $end_ymd) {
388
389	        ($sec,$min,$hr,$cat_date,$cat_mnth,$cat_yr,$day,$yr_date,$DST) = localtime($cat_end_epoch);
390	        $cat_mnth++;
391	        $cat_yr += 1900;
392	        if ((0 < $cat_mnth) && ($cat_mnth < 10)) { $cat_mnth = "0" . $cat_mnth; }
393	        if ((0 < $cat_date) && ($cat_date < 10)) { $cat_date = "0" . $cat_date; }
394
395		if ($exporter ne "") {
396	               	$cat_directory = "$exporter_directory";
397		} else {
398	               	$cat_directory = "$flow_data_directory/$device_name";
399		}
400
401		if ($N == -3) { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
402		if ($N == -2) { $cat_directory .= "/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
403		if ($N == -1) { $cat_directory .= "/$cat_yr\-$cat_mnth\-$cat_date"; }
404		if ($N == 1)  { $cat_directory .= "/$cat_yr"; }
405		if ($N == 2)  { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth"; }
406		if ($N == 3)  { $cat_directory .= "/$cat_yr/$cat_yr\-$cat_mnth/$cat_yr\-$cat_mnth\-$cat_date"; }
407
408	        $concatenate_parameters .= "$cat_directory ";
409	}
410	else {
411	        &print_error("Start day ($start_date) is past End day ($end_date)");
412	}
413
414	# Create the filter to match the input specifications
415
416	$filter_file = "$work_directory/FlowViewer_filter_$suffix";
417
418	create_filter_file(%FORM,$filter_file);
419
420	# Set up the command to concatenate the files
421
422	$flowcat_command = "$flow_bin_directory/flow-cat" . " $concatenate_parameters";
423
424	# Set up the command to filter the concatenated file
425
426	$flownfilter_command = "$flow_bin_directory/flow-nfilter -f $work_directory/FlowViewer_filter_$suffix -FFlow_Filter";
427
428	# Set up the flow-stat command if requested
429
430	if ($stat_report ne "0") {
431		if ($rate_report) {
432			if ($sort_field == 1) { $ft_sort_field = 3; }
433			if ($sort_field == 2) { $ft_sort_field = 2; }
434			if ($sort_field == 3) { $ft_sort_field = 4; }
435		} else {
436			if ($sort_field == 1) { $ft_sort_field = 2; }
437			if ($sort_field == 2) { $ft_sort_field = 1; }
438			if ($sort_field == 3) { $ft_sort_field = 3; }
439		}
440		if ($stat_report eq "99") {
441	        	$flowstat_command = "$flow_bin_directory/flow-stat -S$ft_sort_field >$work_directory/FlowViewer_output_$suffix";
442	        	$flow_run = "$flowcat_command | $flownfilter_command | $flowstat_command 2>>$work_directory/FlowViewer_output_$suffix";
443		} elsif ($stat_report == 30) {
444			if (($source_ifs ne "") || ($sif_names ne "")) { $in_int_list  = "-i" . $source_ifs . $sif_names; } else {  $in_int_list = ""; }
445			if (($dest_ifs   ne "") || ($dif_names ne "")) { $out_int_list = "-I" . $dest_ifs   . $dif_names; } else { $out_int_list = ""; }
446			$suppress_list = "$cgi_bin_directory/dscan.suppress";
447			$touch_command = "touch $suppress_list.src $suppress_list.dst";
448			system($touch_command);
449			$flow_prefilter = "$flowcat_command | $flownfilter_command > $work_directory/FlowViewer_scanner_$suffix";
450			system($flow_prefilter);
451			$flow_run = "$flow_bin_directory/flow-dscan $in_int_list $out_int_list -L$suppress_list -b $dscan_parameters < $work_directory/FlowViewer_scanner_$suffix >&$work_directory/FlowViewer_output_$suffix";
452		} else {
453	        	$flowstat_command = "$flow_bin_directory/flow-stat -f$stat_report -S$ft_sort_field >$work_directory/FlowViewer_output_$suffix";
454	        	$flow_run = "$flowcat_command | $flownfilter_command | $flowstat_command 2>>$work_directory/FlowViewer_output_$suffix";
455		}
456	}
457
458	# Set up the flow-print command if requested
459
460	if ($print_report ne "0") {
461	        $flowprint_command = "$flow_bin_directory/flow-print -f$print_report >$work_directory/FlowViewer_output_$suffix";
462	        $flow_run = "$flowcat_command | $flownfilter_command | $flowprint_command 2>>$work_directory/FlowViewer_output_$suffix";
463	}
464
465	# Execute the piped flow-tools command
466
467	if ($debug_viewer eq "Y") { print DEBUG "\n$flow_run\n\n"; }
468
469	system ($flow_run);
470
471} else {
472
473	$silk_cat_start = $start_epoch - $silk_capture_buffer_pre;
474	$silk_cat_end   = $end_epoch   + $silk_capture_buffer_post;
475
476	if ($silk_compiled_localtime eq "Y") {
477		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime($silk_cat_start);
478	} else {
479		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = gmtime($silk_cat_start);
480	}
481	$yr += 1900;
482	$mnth++;
483	if (length($mnth) < 2) { $mnth = "0" . $mnth; }
484	if (length($date) < 2) { $date = "0" . $date; }
485	if (length($hr)   < 2) { $hr   = "0" . $hr; }
486	$silk_cat_start    = $yr ."/". $mnth ."/". $date .":". $hr;
487
488	if ($silk_compiled_localtime eq "Y") {
489		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = localtime($silk_cat_end);
490	} else {
491		($sec,$min,$hr,$date,$mnth,$yr,$day,$yr_date,$DST) = gmtime($silk_cat_end);
492	}
493	$yr += 1900;
494	$mnth++;
495	if (length($mnth) < 2) { $mnth = "0" . $mnth; }
496	if (length($date) < 2) { $date = "0" . $date; }
497	if (length($hr)   < 2) { $hr   = "0" . $hr; }
498	$silk_cat_end = $yr ."/". $mnth ."/". $date .":". $hr;
499
500	# Set up SiLK selection
501
502	$selection_switches = "";
503	if ($silk_rootdir ne "")   { $selection_switches  = "--data-rootdir=$silk_rootdir "; }
504	if ($silk_class ne "")     { $selection_switches .= "--class=$silk_class "; }
505	if ($silk_flowtype ne "")  { $selection_switches .= "--flowtype=$silk_flowtype "; }
506	if ($silk_type ne "")      { $selection_switches .= "--type=$silk_type "; }
507	if ($silk_sensors ne "")   { $selection_switches .= "--sensors=$silk_sensors "; }
508	if ($silk_switches ne "")  { $selection_switches .= "$silk_switches "; }
509
510	$silk_info_out = $selection_switches;
511
512        # Prepare rwfilter start and end time parameters
513
514        $time_window = $silk_period_start ."-". $silk_period_end;
515
516	if ($flow_select eq 1) { $window_type = "--active"; }
517	if ($flow_select eq 2) { $window_type = "--etime"; }
518	if ($flow_select eq 3) { $window_type = "--stime"; }
519	if ($flow_select eq 4) { $window_type = "--stime"; }
520
521	$selection_switches .= "--start-date=$silk_cat_start --end-date=$silk_cat_end $window_type=$time_window ";
522
523        # Prepare source and destination IP address parameters
524
525        create_ipfix_filter(%FORM);
526
527        # Prepare rwfilter command
528
529	if ($debug_viewer eq "Y") { print DEBUG "   selection_switches: $selection_switches\n"; }
530	if ($debug_viewer eq "Y") { print DEBUG "partitioning_switches:$partitioning_switches\n"; }
531
532	$rwfilter_command = "$silk_bin_directory/rwfilter $site_config_modifier $selection_switches $partitioning_switches --pass=stdout";
533
534	if ($print_report == 1) { $rwfilter_command .= " | $silk_bin_directory/rwsort $site_config_modifier --fields=9 "; }
535
536        # Prepare rwstats output fields (this set is similar to flow-tools)
537
538	$column_separator = " ";
539
540	if ($stat_report == 99) { $report_title = "Summary"; }
541	if ($stat_report == 5)  { $field_sequence = "4"; }
542	if ($stat_report == 6)  { $field_sequence = "3"; }
543	if ($stat_report == 7)  { $field_sequence = "3,4"; }
544	if ($stat_report == 8)  { $field_sequence = "2"; }
545	if ($stat_report == 9)  { $field_sequence = "1"; }
546	if ($stat_report == 10) { $field_sequence = "1,2"; }
547	if ($stat_report == 11) { $report_title = "Source or Destination IP";  $heading_1 = "Host"; }
548	if ($stat_report == 12) { $field_sequence = "5"; }
549	if ($stat_report == 17) { $field_sequence = "13"; }
550	if ($stat_report == 18) { $field_sequence = "14"; }
551	if ($stat_report == 19) { &print_error("The Source AS Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
552	if ($stat_report == 20) { &print_error("The Destination AS Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
553	if ($stat_report == 21) { &print_error("The Source/Destination AS Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
554	if ($stat_report == 22) { &print_error("The IP ToS Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
555	if ($stat_report == 23) { $field_sequence = "13,14"; }
556	if ($stat_report == 24) { &print_error("The Statistics Source Prefix Report is not available for IPFIX data. Please use the Source Prefix Aggregation Printed Report."); }
557	if ($stat_report == 25) { &print_error("The Statistics Destination Prefix Report is not available for IPFIX data. Please use the Destination Prefix Aggregation Printed Report."); }
558	if ($stat_report == 26) { &print_error("The Statistics Source/Destination Prefix Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
559	if ($stat_report == 27) { &print_error("The Exporter IP Report is not available for IPFIX data."); }
560	if ($stat_report == 30) { $report_title = "Detect Scanning"; }
561
562	if ($print_report == 1)  { $field_sequence = "22,24,23,13,1,14,2,5,3,4,6,7,8"; }
563	if ($print_report == 4)  { &print_error("The AS Numbers Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
564	if ($print_report == 5)  { $field_sequence = "22,24,23,13,1,3,14,2,4,15,5,6,7,8"; }
565	if ($print_report == 9)  { &print_error("The 1 Line with Tags Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
566	if ($print_report == 10) { &print_error("The AS Aggregation Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
567	if ($print_report == 11) { &print_error("The Protocol Port Aggregation Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
568	if ($print_report == 12) { $field_sequence = "1"; }
569	if ($print_report == 13) { $field_sequence = "2"; }
570	if ($print_report == 14) { &print_error("The Prefix Aggregation report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
571	if ($print_report == 15) { $field_sequence = "1"; }
572	if ($print_report == 16) { $field_sequence = "2"; }
573	if ($print_report == 17) { $field_sequence = "1,2"; }
574	if ($print_report == 24) { &print_error("The Full Catalyst Report is not available for IPFIX data. The capability is not currently supported by SiLK."); }
575
576	if ($sort_field == 1) { $rwstat_values = "Bytes,Packets,Records"; }
577	if ($sort_field == 2) { $rwstat_values = "Records,Bytes,Packets"; }
578	if ($sort_field == 3) { $rwstat_values = "Packets,Bytes,Records"; }
579
580	time_check("start SiLK");
581
582	if ($stat_report == 11) {
583
584		$half_cutoff_lines  = int(0.5 * $cutoff_lines);
585
586		$field_sequence = "1";
587        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --fields=$field_sequence --values=$rwstat_values --no-titles --no-percents --delimited=\"  \" ";
588		if ($cutoff_octets > 0) {
589			$rwstats_command .= "--threshold=$cutoff_octets";
590		} else {
591			$rwstats_command .= "--count=$half_cutoff_lines";
592		}
593        	$silk_command = "$rwfilter_command | $rwstats_command > $work_directory/FlowViewer_output_$suffix";
594		if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
595        	system ($silk_command);
596
597		$field_sequence = "2";
598        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --fields=$field_sequence --values=$rwstat_values --no-titles --no-percents --delimited=\"  \" ";
599		if ($cutoff_octets > 0) {
600			$rwstats_command .= "--threshold=$cutoff_octets";
601		} else {
602			$rwstats_command .= "--count=$half_cutoff_lines";
603		}
604        	$silk_command = "$rwfilter_command | $rwstats_command >> $work_directory/FlowViewer_output_$suffix";
605		if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
606        	system ($silk_command);
607
608		$temp_sort_file = "$work_directory/FlowViewer_output_$suffix";
609		open(TEMPSORT,"<$temp_sort_file");
610		chomp (@temp_sort_lines = <TEMPSORT>);
611		close TEMPSORT;
612		foreach $temp_sort_line (@temp_sort_lines) {
613			($ip_addr,$octs,$pkts,$flws) = split(/\s+/,$temp_sort_line);
614			$num_zeroes = 20 - length($octs);
615			for ($i=0;$i<$num_zeroes;$i++) { $octs = "0" . $octs; }
616			$new_sort_line = $octs ." ". $ip_addr ." ". $pkts ." ". $flws;
617			push(@new_sort_lines,$new_sort_line);
618		}
619
620		@pre_sorted_lines = sort (@new_sort_lines);
621		@newly_sorted_lines = reverse(@pre_sorted_lines);
622		open(TEMPSORT,">$temp_sort_file");
623		foreach $temp_sort_line (@newly_sorted_lines) {
624			($octs,$ip_addr,$pkts,$flws) = split(/\s+/,$temp_sort_line);
625			for ($i=0;$i<20;$i++) { if (substr($octs,0,1) eq "0") { $octs = substr($octs,1,20); } }
626			$sorted_output_line = $ip_addr ." ". $octs ." ". $pkts ." ". $flws;
627			print TEMPSORT "$sorted_output_line\n";
628		}
629		close TEMPSORT;
630
631	} elsif ($stat_report == 30) {
632
633		$prefiltered_file = "$work_directory/FlowViewer_scanner_$suffix";
634		($left_part,$right_part) = split(/--pass=/,$rwfilter_command);
635		$rwfilter_command = $left_part . "--pass=$prefiltered_file";
636        	if ($debug_viewer eq "Y") { print DEBUG "rwfilter_command: $rwfilter_command\n"; }
637        	system ($rwfilter_command);
638		$rwsort_command = "$silk_bin_directory/rwsort $site_config_modifier --fields=sip,proto,dip $prefiltered_file";
639		$rwscan_command = "$silk_bin_directory/rwscan $site_config_modifier --scan-model=$scan_model --trw-internal-set=$trw_internal_set --model-fields";
640        	$silk_command = "$rwsort_command | $rwscan_command > $work_directory/FlowViewer_output_$suffix";
641        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
642        	system ($silk_command);
643
644	} elsif ($stat_report == 99) {
645
646		$field_sequence = "5";
647        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --fields=$field_sequence --values=$rwstat_values --count=1000 --no-titles --no-percents --delimited=\"  \" ";
648        	$silk_command = "$rwfilter_command | $rwstats_command > $work_directory/FlowViewer_summary_$suffix";
649		if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
650        	system ($silk_command);
651
652		open (SUMMARY,"<$work_directory/FlowViewer_summary_$suffix");
653		while (<SUMMARY>) {
654			if (substr($_,0,1) eq "#") { next; }
655			($x,$flows,$octets,$packets) = split(/\s+/,$_);
656			$sum_field_sequence .= "$x,";
657		}
658
659		chop $sum_field_sequence;
660        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --detail-proto-stats=$sum_field_sequence";
661        	$silk_command = "$rwfilter_command | $rwstats_command > $work_directory/FlowViewer_output_$suffix";
662        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
663        	system ($silk_command);
664
665	} elsif (($print_report == 1) || ($print_report == 5)) {
666
667		$sort_field = 5;
668        	$rwcut_command = "$silk_bin_directory/rwcut $site_config_modifier --fields=$field_sequence --column-separator=\"  \"";
669		if ($cutoff_lines > 0) { $rwcut_command .= "--num-recs=$cutoff_lines"; }
670        	$silk_command = "$rwfilter_command | $rwcut_command > $work_directory/FlowViewer_output_$suffix";
671        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
672        	system ($silk_command);
673
674	} elsif (($print_report >= 12) && ($print_report <= 17)) {
675
676		if ($print_report == 12) { $rwnetmask_command = "$silk_bin_directory/rwnetmask $site_config_modifier --sip-prefix-length  $sip_prefix_length"; }
677		if ($print_report == 13) { $rwnetmask_command = "$silk_bin_directory/rwnetmask $site_config_modifier --dip-prefix-length  $dip_prefix_length"; }
678		if ($print_report == 15) { $rwnetmask_command = "$silk_bin_directory/rwnetmask $site_config_modifier --6sip-prefix-length $sip_prefix_length --ipv6-policy=only"; }
679		if ($print_report == 16) { $rwnetmask_command = "$silk_bin_directory/rwnetmask $site_config_modifier --6dip-prefix-length $dip_prefix_length --ipv6-policy=only"; }
680		if ($print_report == 17) { $rwnetmask_command = "$silk_bin_directory/rwnetmask $site_config_modifier --6sip-prefix-length $sip_prefix_length --6dip-prefix-length $dip_prefix_length --ipv6-policy=only"; }
681
682        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --fields=$field_sequence --values=$rwstat_values --no-titles --no-percents --delimited=\"  \" ";
683		if ($cutoff_octets > 0) {
684			$rwstats_command .= "--threshold=$cutoff_octets";
685		} else {
686			$rwstats_command .= "--count=$cutoff_lines";
687		}
688        	$silk_command = "$rwfilter_command | $rwnetmask_command | $rwstats_command > $work_directory/FlowViewer_output_$suffix";
689        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
690        	system ($silk_command);
691
692	} else {
693
694        	$rwstats_command = "$silk_bin_directory/rwstats $site_config_modifier --fields=$field_sequence --values=$rwstat_values --no-titles --no-percents --delimited=\"  \" ";
695		if ($cutoff_octets > 0) {
696			$rwstats_command .= "--threshold=$cutoff_octets";
697		} else {
698			$rwstats_command .= "--count=$cutoff_lines";
699		}
700        	$silk_command = "$rwfilter_command | $rwstats_command > $work_directory/FlowViewer_output_$suffix";
701        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
702        	system ($silk_command);
703	}
704	time_check("end SiLK");
705}
706
707$heading_1 = ""; $heading_2 = "";
708
709if ($stat_report == 99) { $report_title = "Summary"; }
710if ($stat_report == 5)  { $report_title = "UDP/TCP Destination Port";  $heading_1 = "Dst Port"; }
711if ($stat_report == 6)  { $report_title = "UDP/TCP Source Port";       $heading_1 = "Src Port"; }
712if ($stat_report == 7)  { $report_title = "UDP/TCP Port";              $heading_1 = "Port"; }
713if (($stat_report == 7) && ($IPFIX)) {                                 $heading_1 = "Src Port"; $heading_2 = "Dst Port";}
714if ($stat_report == 8)  { $report_title = "Destination IP";            $heading_1 = "Dst Host"; }
715if ($stat_report == 9)  { $report_title = "Source IP";                 $heading_1 = "Src Host"; }
716if ($stat_report == 10) { $report_title = "Source/Destination IP";     $heading_1 = "Src Host"; $heading_2 = "Dst Host"; $rate_report = 1;}
717if ($stat_report == 11) { $report_title = "Source or Destination IP";  $heading_1 = "Host"; }
718if ($stat_report == 12) { $report_title = "IP Protocol";               $heading_1 = "Protocol"; }
719if ($stat_report == 17) { $report_title = "Input Interface";           $heading_1 = "In I/F"; }
720if ($stat_report == 18) { $report_title = "Output Interface";          $heading_1 = "Out I/F"; }
721if ($stat_report == 19) { $report_title = "Source AS";                 $heading_1 = "Src AS"; }
722if ($stat_report == 20) { $report_title = "Destination AS";            $heading_1 = "Dst AS"; }
723if ($stat_report == 21) { $report_title = "Source/Destination AS";     $heading_1 = "Src AS"; $heading_2 = "Dst AS"; $rate_report = 1;}
724if ($stat_report == 22) { $report_title = "IP ToS";                    $heading_1 = "ToS"; }
725if ($stat_report == 23) { $report_title = "Input/Output Interface";    $heading_1 = "In I/F"; $heading_2 = "Out I/F"; $rate_report = 1;}
726if ($stat_report == 24) { $report_title = "Source Prefix";             $heading_1 = "Src Prefix"; }
727if ($stat_report == 25) { $report_title = "Destination Prefix";        $heading_1 = "Dst Prefix"; }
728if ($stat_report == 26) { $report_title = "Source/Destination Prefix"; $heading_1 = "Src Prefix"; $heading_2 = "Dst Prefix"; $rate_report = 1;}
729if ($stat_report == 27) { $report_title = "Exporter IP";               $heading_1 = "Exporter"; }
730if ($stat_report == 30) { $report_title = "Detect Scanning";           $heading_1 = "Detect Scanning"; }
731
732$resolve_columns = 0;
733if (($resolve_addresses eq "Y") && ($stat_report == 8))  { $resolve_columns = 1; }
734if (($resolve_addresses eq "Y") && ($stat_report == 9))  { $resolve_columns = 1; }
735if (($resolve_addresses eq "Y") && ($stat_report == 10)) { $resolve_columns = 2; }
736if (($resolve_addresses eq "Y") && ($stat_report == 11)) { $resolve_columns = 1; }
737if (($resolve_addresses eq "Y") && ($stat_report == 17)) { $resolve_columns = 5; }
738if (($resolve_addresses eq "Y") && ($stat_report == 18)) { $resolve_columns = 5; }
739if (($resolve_addresses eq "Y") && ($stat_report == 19)) { $resolve_columns = 3; }
740if (($resolve_addresses eq "Y") && ($stat_report == 20)) { $resolve_columns = 3; }
741if (($resolve_addresses eq "Y") && ($stat_report == 21)) { $resolve_columns = 4; }
742if (($resolve_addresses eq "Y") && ($stat_report == 23)) { $resolve_columns = 6; }
743if (($resolve_addresses eq "Y") && ($stat_report == 27)) { $resolve_columns = 7; }
744
745if ($print_report == 1)  { $report_title = "Flow Times"; }
746if ($print_report == 4)  { $report_title = "AS Numbers"; }
747if ($print_report == 5)  { $report_title = "132 Columns"; }
748if ($print_report == 9)  { $report_title = "1 Line with Tags"; }
749if ($print_report == 10) { $report_title = "AS Aggregation"; }
750if ($print_report == 11) { $report_title = "Protocol Port Aggregation"; }
751if ($print_report == 12) { $report_title = "Source Prefix Aggregation";      if ($IPFIX) { $heading_1 = "Source Prefix"; }}
752if ($print_report == 13) { $report_title = "Destination Prefix Aggregation"; if ($IPFIX) { $heading_1 = "Dest Prefix"; }}
753if ($print_report == 14) { $report_title = "Prefix Aggregation"; $heading_1 = "Source Aggregate"; $heading_2 = "Dest Aggregate"; }
754if ($print_report == 15) { $report_title = "Source Prefix Aggregation v6";      $heading_1 = "Source Prefix"; }
755if ($print_report == 16) { $report_title = "Destination Prefix Aggregation v6"; $heading_1 = "Dest Prefix"; }
756if ($print_report == 17) { $report_title = "Prefix Aggregation v6"; $heading_1 = "Source Aggregate"; $heading_2 = "Dest Aggregate"; }
757if ($print_report == 24) { $report_title = "Full (Catalyst)"; }
758if(($print_report >  0) && (!$IPFIX)) { $sort_field = 4; }
759
760$short_fields = 0;
761if ($resolve_columns == 0) {
762	if (($stat_report ==  5) || ($stat_report ==  6) || ($stat_report ==  7)) { $short_fields = 1; }
763	if (($stat_report >= 12) && ($stat_report <= 23))                         { $short_fields = 1; }
764}
765
766# Determine whether to translate interface indexes
767
768if (($resolve_columns != 0) && (($stat_report == 17) || ($stat_report == 18) || ($stat_report == 23))) {
769	$short_fields = 1;
770	$interface_names = 0;
771	$test_if = 1;
772	$if_name = dig_if($test_if);
773	if ($if_name ne "NO_TRANSLATIONS") { $interface_names = 1; $short_fields = 0; }
774}
775
776# Output report input filtering criteria
777
778$start_flows_out = $start_flows ." $time_zone";
779$end_flows_out   = $end_flows ." $time_zone";
780if ($sort_field == 1) { $sort_field_out = "Octets"; }
781if ($sort_field == 2) { $sort_field_out = "Flows"; }
782if ($sort_field == 3) { $sort_field_out = "Packets"; }
783if ($sort_field == 4) { $sort_field_out = "N/A"; }
784if ($sort_field == 5) { $sort_field_out = "sTime"; }
785
786# Generate a pie-chart if the user is interested
787
788$piechart_link = "no piechart";
789if (($pie_charts > 0) && ((($stat_report > 0 ) && ($stat_report < 30)) || (($print_report > 10) && ($print_report <18)))) {
790
791	$array_elements = $number_slices - 1;
792
793	open (OUTPUT,"<$work_directory/FlowViewer_output_$suffix");
794	while (<OUTPUT>) {
795
796		if (substr($_,0,1) eq "#") { next; }
797
798		$line_count++;
799
800		if (($rate_report) || (($stat_report == 7) && ($IPFIX)) || ($print_report == 14) || ($print_report == 17)) {
801			if ($IPFIX) {
802				if ($sort_field == 1) { ($x,$y,$octets,$packets,$flows) = split(/\s+/,$_); }
803				if ($sort_field == 2) { ($x,$y,$flows,$octets,$packets) = split(/\s+/,$_); }
804				if ($sort_field == 3) { ($x,$y,$packets,$octets,$flows) = split(/\s+/,$_); }
805			} else {
806				($x,$y,$flows,$octets,$packets) = split(/\s+/,$_);
807			}
808		} else {
809			if ($IPFIX) {
810				if ($sort_field == 1) { ($x,$octets,$packets,$flows) = split(/\s+/,$_); }
811				if ($sort_field == 2) { ($x,$flows,$octets,$packets) = split(/\s+/,$_); }
812				if ($sort_field == 3) { ($x,$packets,$octets,$flows) = split(/\s+/,$_); }
813			} else {
814				($x,$flows,$octets,$packets)    = split(/\s+/,$_);
815			}
816		}
817
818                $IPv4_y = 0; $IPv6_y = 0;
819                if ($y =~ m/^\s*-*\d+/) {
820                        $_ = $y;
821                        $num_dots   = tr/\.//; if ($num_dots   > 0) { $IPv4_y = 1; }
822                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_y = 1; }
823                }
824
825		if (($stat_report != 0) && ($octets < $cutoff_octets)) { last; }
826
827		if ($top_count < $array_elements) {
828			if ($sort_field == 1) { $top_ten_values[$top_count] = $octets; }
829			if ($sort_field == 2) { $top_ten_values[$top_count] = $flows; }
830			if ($sort_field == 3) { $top_ten_values[$top_count] = $packets; }
831			$x_out = $x;
832			$y_out = $y;
833			if ($resolve_columns == 0) {
834		                $IPv6_x = 0;
835		                if ($x_out =~ m/^\s*-*\d+/) {
836		                        $_ = $x_out;
837		                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_x = 1; }
838		                }
839				if ($IPv6_x) {
840					$last_colon = rindex($x_out,":") - 1;
841					$last_colon = rindex($x_out,":",$last_colon);
842					$x_out = "..." . substr($x_out,$last_colon,18);
843				} else {
844					if ($x_out =~ /[a-zA-Z]/) { ($x_out) = split(/\./,$x_out); }
845				}
846			}
847			if (($resolve_columns == 1) || ($resolve_columns == 2)) {
848				$x_out = dig($x);
849		                $IPv6_x = 0;
850		                if ($x_out =~ m/^\s*-*\d+/) {
851		                        $_ = $x_out;
852		                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_x = 1; }
853		                }
854				if ($IPv6_x) {
855					$last_colon = rindex($x_out,":") - 1;
856					$last_colon = rindex($x_out,":",$last_colon);
857					$x_out = "..." . substr($x_out,$last_colon,18);
858				} else {
859					if ($x_out =~ /[a-zA-Z]/) { ($x_out) = split(/\./,$x_out); }
860				}
861			}
862			if ($resolve_columns == 3) {
863				$x_out = dig_as($x);
864			}
865			if (($resolve_columns == 5) && ($interface_names)) {
866				$x_out = dig_if($x);
867			}
868			if ($resolve_columns == 7) {
869				$x_out = dig_ex($x);
870		                $IPv6_x = 0;
871		                if ($x_out =~ m/^\s*-*\d+/) {
872		                        $_ = $x_out;
873		                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_x = 1; }
874		                }
875				if ($IPv6_x) {
876					$last_colon = rindex($x_out,":") - 1;
877					$last_colon = rindex($x_out,":",$last_colon);
878					$x_out = "..." . substr($x_out,$last_colon,18);
879				} else {
880					if ($x_out =~ /[a-zA-Z]/) { ($x_out) = split(/\./,$x_out); }
881				}
882			}
883			$top_ten_labels[$top_count] = $x_out;
884			if ($y ne "") {
885				if ($resolve_columns == 0) {
886			                $IPv6_y = 0;
887			                if ($y_out =~ m/^\s*-*\d+/) {
888			                        $_ = $y_out;
889			                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_y = 1; }
890			                }
891					if ($IPv6_y) {
892						$last_colon = rindex($y_out,":") - 1;
893						$last_colon = rindex($y_out,":",$last_colon);
894						$y_out = "..." . substr($y_out,$last_colon,18);
895					} else {
896						if ($y_out =~ /[a-zA-Z]/) { ($y_out) = split(/\./,$y_out); }
897					}
898				}
899				if (($resolve_columns == 1) || ($resolve_columns == 2)) {
900					$y_out = dig($y);
901			                $IPv6_y = 0;
902			                if ($y_out =~ m/^\s*-*\d+/) {
903			                        $_ = $y_out;
904			                        $num_colons = tr/\://; if ($num_colons > 0) { $IPv6_y = 1; }
905			                }
906					if ($IPv6_y) {
907						$last_colon = rindex($y_out,":") - 1;
908						$last_colon = rindex($y_out,":",$last_colon);
909						$y_out = "..." . substr($y_out,$last_colon,18);
910					} else {
911						if ($y_out =~ /[a-zA-Z]/) { ($y_out) = split(/\./,$y_out); }
912					}
913				}
914				if ($resolve_columns == 4) {
915					$y_out = dig_as($y);
916				}
917				if (($resolve_columns == 6) && ($interface_names)) {
918					$y_out = dig_if($y);
919				}
920				$top_ten_labels[$top_count] .= " - ". $y_out;
921			}
922			$top_count++;
923		} elsif ($pie_charts == 1) {
924			if ($sort_field == 1) { $top_ten_values[$top_count] += $octets; }
925			if ($sort_field == 2) { $top_ten_values[$top_count] += $flows; }
926			if ($sort_field == 3) { $top_ten_values[$top_count] += $packets; }
927			$top_ten_labels[$array_elements] = "Other";
928		}
929
930		if (($line_count-3) > $cutoff_lines) { last; }
931	}
932
933	if ($line_count eq "") {
934
935		print " </div>\n";
936		&create_UI_service("FlowViewer_Main","service_bottom",$active_dashboard,$filter_hash);
937		&finish_the_page("FlowViewer_Main");
938
939		$rm_command = "rm $work_directory/FlowViewer_filter_$suffix";
940		if ($debug_files ne "Y") { system($rm_command); }
941		$rm_command = "rm $work_directory/FlowViewer_output_$suffix";
942		if ($debug_files ne "Y") { system($rm_command); }
943
944		exit;
945
946	} else { $line_count = 0; }
947
948	$graph = new GD::Graph::pie(325,175);
949
950	$graph->set(
951	    transparent     => 1,
952	    axislabelclr    => 'black',
953	    dclrs           => $pie_colors,
954	    '3d'            => 1,
955	    pie_height      => 10,
956	    start_angle     => 90,
957	    suppress_angle  => 20
958	)
959	or warn $graph->error;
960
961	$graph->set_label_font(GD::Font->Small);
962	$graph->set_value_font(GD::Font->Small);
963
964	@plot = ([@top_ten_labels],[@top_ten_values]);
965	$image = $graph->plot(\@plot) or die $graph->error;
966
967	$png_filename = "FlowViewer_save_" . $saved_suffix . ".png";
968	$piechart_link = "$graphs_short/$png_filename";
969
970	open(PNG,">$graphs_directory/$png_filename");
971	binmode PNG;
972	print PNG $image->png;
973
974	print "<center><img src=$piechart_link></center>\n";
975	print HTML "<center><img src=$piechart_link></center>\n";
976
977	close (OUTPUT);
978}
979
980# Parse through the intermediate, flow tools (or now SiLK) generated, 'FlowViewer_output' file
981
982$print_header  = 1;
983$first_scanner = 1;
984
985$sort_file = "$work_directory/FlowViewer_save_" . $saved_suffix;
986open (SORTED_SAVE, ">$sort_file");
987&start_saved_file($sort_file);
988open (SORTED_SAVE, ">>$sort_file");
989
990if ((($print_report > 0) && ($print_report < 12)) || ($stat_report == 99)) {
991	print " <pre><font face=\"Courier New\">\n";
992	print " <table>\n";
993	print SORTED_SAVE " <pre><font face=\"Courier New\">\n";
994	print SORTED_SAVE " <table>\n";
995}
996
997open (OUTPUT,"<$work_directory/FlowViewer_output_$suffix");
998while (<OUTPUT>) {
999
1000	chop;
1001	if (substr($_,0,1) eq "#") { next; }
1002	if (substr($_,0,5) eq "flow-") {
1003		if ($stat_report == 30) {
1004			if (!$start_table) {
1005
1006				$report_suffix = &get_suffix;
1007				$report_filename = "FlowViewer_save_$report_suffix";
1008				$filter_hash = "SC_$report_filename";
1009				$main_hash = $filter_hash;
1010				$report_file = "$work_directory/$report_filename";
1011				open (SCAN_SAVE, ">$report_file");
1012				&start_saved_file($report_file);
1013				close (SCAN_SAVE);
1014				open (SCAN_SAVE, ">>$report_file");
1015
1016				print " <table>\n";
1017				print " <tr><td>&nbsp</td></tr>\n";
1018				print " <tr><td align=left>The following hosts were discovered to be scanners</td></tr>\n";
1019				print " <tr><td>&nbsp</td></tr>\n";
1020				print " </table>\n";
1021				print " <table>\n";
1022				print " <tr>\n";
1023				print "<td>IP Address</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1024				print "<td>Host Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1025				print "<td>CC</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1026				print "<td>AS Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1027				print "<td>Flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1028				print "<td>Avg Fl Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1029				print "<td>Avg Pkt Size</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1030				print "<td>Pkts/Flow</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1031				print "<td>Flows/Sec</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1032				print "</tr>\n";
1033				print " <tr><td>&nbsp</td></tr>\n";
1034
1035				print SCAN_SAVE " <table>\n";
1036				print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1037				print SCAN_SAVE " <tr><td align=left>The following hosts were discovered to be scanners</td></tr>\n";
1038				print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1039				print SCAN_SAVE " </table>\n";
1040				print SCAN_SAVE " <table>\n";
1041				print SCAN_SAVE " <tr>\n";
1042				print SCAN_SAVE "<td>IP Address</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1043				print SCAN_SAVE "<td>Host Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1044				print SCAN_SAVE "<td>CC</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1045				print SCAN_SAVE "<td>AS Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1046				print SCAN_SAVE "<td>Flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1047				print SCAN_SAVE "<td>Avg Fl Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1048				print SCAN_SAVE "<td>Avg Pkt Size</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1049				print SCAN_SAVE "<td>Pkts/Flow</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1050				print SCAN_SAVE "<td>Flows/Sec</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1051				print SCAN_SAVE "</tr>\n";
1052				print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1053				$start_table = 1;
1054			}
1055			if (substr($_,0,16) eq "flow-dscan: host") {
1056
1057				($left_part,$right_part) = split(/ ts=/);
1058				($left_part,$ip_address) = split(/=/,$left_part);
1059
1060				$scan_suffix = &get_suffix;
1061				$scan_filename = "FlowViewer_save_$scan_suffix";
1062				$scan_hash  = "SC_$scan_filename";
1063				$scan_file = "$work_directory/$scan_filename";
1064				$stats_file = "$work_directory/FlowViewer_scan_stats";
1065				$filter_hash = $scan_hash;
1066				$source_addresses = $ip_address;
1067				open (SORTED_SAVE, ">$scan_file");
1068				&start_saved_file($scan_file);
1069				close (SORTED_SAVE);
1070				$filter_hash = $main_hash;
1071
1072				$ip_name  = dig($ip_address);
1073				($as_number,$as_country,$as_name) = dig_as_full($ip_address);
1074
1075				$filter_file = "$work_directory/FlowViewer_filter_scanner";
1076				$FORM{source_address} = $ip_address;
1077				$FORM{cutoff_lines} = 2000;
1078				create_filter_file(%FORM,$filter_file);
1079				$flownfilter_command = "$flow_bin_directory/flow-nfilter -f $work_directory/FlowViewer_filter_scanner -FFlow_Filter";
1080				$flowprint_command = "$flow_bin_directory/flow-print -f5 >>$scan_file";
1081				$flow_run = "$flownfilter_command <$work_directory/FlowViewer_scanner_$suffix | $flowprint_command";
1082				system($flow_run);
1083
1084				$flowstat_command = "$flow_bin_directory/flow-stat -f0 >$stats_file";
1085				$flow_run = "$flownfilter_command <$work_directory/FlowViewer_scanner_$suffix | $flowstat_command";
1086				system($flow_run);
1087				open(STATS,"<$stats_file");
1088                		while (<STATS>) {
1089					if ((substr($_,0,1) eq "#") || (substr($_,0,1) eq " ")) { next; }
1090					($field_name,$field_value) = split(/: /);
1091					if (/Total Flows/)         { $total_flows   = $field_value; }
1092					if (/Average flow time/)   {
1093						$avg_flow_time = $field_value;
1094						$avg_flow_time *= 0.001;
1095						if ($avg_flow_time < 0.001) { $avg_flow_time = "0.000"; }
1096						$avg_flow_time = substr($avg_flow_time,0,5);
1097					}
1098					if (/Average packet size/) { $avg_pkt_size  = $field_value; }
1099					if (/Average packets per/) { $avg_pkt_flow  = $field_value; }
1100					if (/Average flows \/ se/) { $avg_flow_sec  = $field_value; }
1101				}
1102				$rm_command = "rm $stats_file";
1103				system($rm_command);
1104
1105				$cgi_link = "$cgi_bin_short/FlowViewer_Replay.cgi?$active_dashboard^filter_hash=$scan_hash";
1106				print "<tr><td align=left><a href=$cgi_link>$ip_address</a></td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1107				print "<td>$ip_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1108				print "<td>$as_country</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1109				print "<td>$as_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1110				print "<td align=right>$total_flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1111				print "<td align=right>$avg_flow_time</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1112				print "<td align=right>$avg_pkt_size</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1113				print "<td align=right>$avg_pkt_flow</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1114				print "<td align=right>$avg_flow_sec</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1115				print "</tr>\n";
1116
1117				print SCAN_SAVE "<tr><td align=left><a>$ip_address</a></td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1118				print SCAN_SAVE "<td>$ip_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1119				print SCAN_SAVE "<td>$as_country</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1120				print SCAN_SAVE "<td>$as_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1121				print SCAN_SAVE "<td align=right>$total_flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1122				print SCAN_SAVE "<td align=right>$avg_flow_time</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1123				print SCAN_SAVE "<td align=right>$avg_pkt_size</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1124				print SCAN_SAVE "<td align=right>$avg_pkt_flow</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1125				print SCAN_SAVE "<td align=right>$avg_flow_sec</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1126				print SCAN_SAVE "</tr>\n";
1127				next;
1128			}
1129
1130		} else {
1131			if (!$start_table) {
1132				print " <table>\n";
1133				print " <tr><td>&nbsp</td></tr>\n";
1134				print " <tr><td align=left>Error: Examine presense of flow data for time period specified, etc.</td></tr>\n";
1135				print " <tr><td>&nbsp</td></tr>\n";
1136				$start_table = 1;
1137			}
1138			print " <tr><td align=left>$_</td></tr>\n";
1139			next;
1140		}
1141	}
1142
1143	if (($IPFIX) && ($stat_report == 30)) {
1144
1145		if (!$start_table) {
1146
1147			$report_suffix = &get_suffix;
1148			$report_filename = "FlowViewer_save_$report_suffix";
1149			$filter_hash = "SC_$report_filename";
1150			$main_hash = $filter_hash;
1151			$report_file = "$work_directory/$report_filename";
1152			open (SCAN_SAVE, ">$report_file");
1153			&start_saved_file($report_file);
1154			close (SCAN_SAVE);
1155			open (SCAN_SAVE, ">>$report_file");
1156
1157			print " <table>\n";
1158			print " <tr><td>&nbsp</td></tr>\n";
1159			print " <tr><td align=left>The following hosts were discovered to be scanners</td></tr>\n";
1160			print " <tr><td>&nbsp</td></tr>\n";
1161			print " </table>\n";
1162			print " <table>\n";
1163			print " <tr>\n";
1164			print " <td>IP Address</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1165			print " <td>Host Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1166			print " <td>CC</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1167			print " <td>AS Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1168			print " <td>Start Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1169			print " <td>End Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1170			print " <td>Flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1171			print " <td>Packets</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1172			print " <td>Octets</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1173			print " </tr>\n";
1174			print " <tr><td>&nbsp</td></tr>\n";
1175
1176			print SCAN_SAVE " <table>\n";
1177			print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1178			print SCAN_SAVE " <tr><td align=left>The following hosts were discovered to be scanners</td></tr>\n";
1179			print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1180			print SCAN_SAVE " </table>\n";
1181			print SCAN_SAVE " <table>\n";
1182			print SCAN_SAVE " <tr>\n";
1183			print SCAN_SAVE " <td>IP Address</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1184			print SCAN_SAVE " <td>Host Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1185			print SCAN_SAVE " <td>CC</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1186			print SCAN_SAVE " <td>AS Name</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1187			print SCAN_SAVE " <td>Start Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1188			print SCAN_SAVE " <td>End Time</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1189			print SCAN_SAVE " <td>Flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1190			print SCAN_SAVE " <td>Packets</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1191			print SCAN_SAVE " <td>Octets</td><td>&nbsp&nbsp&nbsp&nbsp</td>\n";
1192			print SCAN_SAVE " </tr>\n";
1193			print SCAN_SAVE " <tr><td>&nbsp</td></tr>\n";
1194			$start_table = 1;
1195		}
1196
1197		($sip,$proto,$stime,$etime,$flows,$packets,$octets) = split(/\|/,$_);
1198
1199		$sip     =~ s/^\s+//;
1200		$proto   =~ s/^\s+//;
1201		$stime   =~ s/^\s+//;
1202		$etime   =~ s/^\s+//;
1203		$flows   =~ s/^\s+//;
1204		$packets =~ s/^\s+//;
1205		$octets  =~ s/^\s+//;
1206
1207		if ($sip eq "sip") { next; }
1208
1209		if ($flow_analysis) {
1210			$oct_per_flow = int($octets / $flows);
1211			$pkt_per_flow = int($packets / $flows);
1212		}
1213
1214		$FORM{source_address} = $sip;
1215        	create_ipfix_filter(%FORM);
1216
1217		$scan_suffix = &get_suffix;
1218		$scan_filename = "FlowViewer_save_$scan_suffix";
1219		$scan_hash  = "SC_$scan_filename";
1220		$scan_file = "$work_directory/$scan_filename";
1221		$stats_file = "$work_directory/FlowViewer_scan_stats";
1222		$filter_hash = $scan_hash;
1223		$source_addresses = $sip;
1224		$cutoff_lines = 1000;
1225		open (SORTED_SAVE, ">$scan_file");
1226		&start_saved_file($scan_file);
1227		close (SORTED_SAVE);
1228		$filter_hash = $main_hash;
1229
1230		$rwfilter_command = "$silk_bin_directory/rwfilter $site_config_modifier $partitioning_switches --pass=stdout $prefiltered_file";
1231                $field_sequence = "22,23,10,13,1,3,14,2,4,5,8,6,7";
1232                $rwcut_command  = "$silk_bin_directory/rwcut $site_config_modifier --fields=$field_sequence --delimited=\"  \" ";
1233        	$silk_command = "$rwfilter_command | $rwcut_command >> $scan_file";
1234        	if ($debug_viewer eq "Y") { print DEBUG "silk_command: $silk_command\n"; }
1235        	system ($silk_command);
1236
1237		$sip_name = dig($sip);
1238		($as_number,$as_country,$as_name) = dig_as_full($sip);
1239
1240		$cgi_link = "$cgi_bin_short/FlowViewer_Replay.cgi?$active_dashboard^filter_hash=$scan_hash";
1241		print "<tr><td align=left><a href=$cgi_link>$sip</a></td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1242		print "<td>$sip_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1243		print "<td>$as_country</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1244		print "<td>$as_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1245		print "<td align=right>$stime</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1246		print "<td align=right>$etime</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1247		print "<td align=right>$flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1248		print "<td align=right>$packets</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1249		print "<td align=right>$octets</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1250		print "</tr>\n";
1251
1252		print SCAN_SAVE "<tr><td align=left><a>$sip</a></td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1253		print SCAN_SAVE "<td>$sip_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1254		print SCAN_SAVE "<td>$as_country</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1255		print SCAN_SAVE "<td>$as_name</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1256		print SCAN_SAVE "<td align=right>$stime</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1257		print SCAN_SAVE "<td align=right>$etime</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1258		print SCAN_SAVE "<td align=right>$flows</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1259		print SCAN_SAVE "<td align=right>$packets</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1260		print SCAN_SAVE "<td align=right>$octets</td><td>&nbsp&nbsp&nbsp&nbsp</td>";
1261		print SCAN_SAVE "</tr>\n";
1262		next;
1263	}
1264
1265	if ((($print_report > 0) && (!$IPFIX)) || (($print_report > 0) && ($print_report < 12)) || ($stat_report == 99) || ($stat_report == 30)) {
1266
1267		$line_count++;
1268		if ((($line_count-1) > $cutoff_lines) && ($stat_report != 99)) { last; }
1269
1270		if (($print_report == 5) && (/DstP    P/)) { s/DstP    P/DstP  P  /; }
1271
1272		if (($stat_report == 99) && (!$IPFIX) && ($sampling_multiplier > 1)) {
1273			$line = $_;
1274                	($field_name,$field_value) = split(/:/,$line);
1275	                if (($line =~ /Total Flows/)   || ($line =~ /Total Octets/) ||
1276	                    ($line =~ /Total Packets/) || ($line =~ /Total Time/)   ||
1277	                    ($line =~ /Average flows \/ second \(flow\)/) ||
1278	                    ($line =~ /Average flows \/ second \(real\)/) ||
1279	                    ($line =~ /Average Kbits \/ second \(flow\)/) ||
1280	                    ($line =~ /Average Kbits \/ second \(real\)/)) {
1281                        	$field_value *= $sampling_multiplier;
1282                        	$field_value .= "*";
1283                        	$line = $field_name .": $field_value";
1284			}
1285			print " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1286			print SORTED_SAVE " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1287			next;
1288		} elsif ($stat_report == 30) {
1289			if (substr(0,16) eq "flow-dscan: host") {
1290				$line = $_;
1291				print SORTED_SAVE "$line\n";
1292			}
1293			next;
1294		} elsif (($print_report == 1) && ($date_format =~ /DMY/)) {
1295
1296			# Converting output for data formatting
1297
1298			$line = $_;
1299			if ((substr($line,0,1) eq " ") && (substr($line,1,1) =~ /[0-9]/)) {
1300				$line_mnth = substr($line,1,2);
1301				$line_date = substr($line,3,2);
1302				$temp_mnth = $line_mnth;
1303				substr($line,1,2) = $line_date;
1304				substr($line,3,2) = $temp_mnth;
1305				$line_mnth = substr($line,20,2);
1306				$line_date = substr($line,22,2);
1307				$temp_mnth = $line_mnth;
1308				substr($line,20,2) = $line_date;
1309				substr($line,22,2) = $temp_mnth;
1310			}
1311			print " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1312			print SORTED_SAVE " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1313			next;
1314		} elsif (($print_report == 5) && ($date_format =~ /DMY/)) {
1315
1316			# Converting output for data formatting
1317
1318			$line = $_;
1319			if (substr($line,0,1) =~ /[0-9]/) {
1320				$line_mnth = substr($line,0,2);
1321				$line_date = substr($line,2,2);
1322				$temp_mnth = $line_mnth;
1323				substr($line,0,2) = $line_date;
1324				substr($line,2,2) = $temp_mnth;
1325				$line_mnth = substr($line,18,2);
1326				$line_date = substr($line,20,2);
1327				$temp_mnth = $line_mnth;
1328				substr($line,18,2) = $line_date;
1329				substr($line,20,2) = $temp_mnth;
1330			}
1331			print " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1332			print SORTED_SAVE " <tr><td align=left><font face=\"Courier New\">$line</font></td></tr>\n";
1333			next;
1334		}
1335		print " <tr><td align=left><font face=\"Courier New\">$_</font></td></tr>\n";
1336		print SORTED_SAVE " <tr><td align=left><font face=\"Courier New\">$_</font></td></tr>\n";
1337		next;
1338	}
1339
1340	if (($stat_report == 8) || ($stat_report == 9) || ($stat_report == 11)) { $country_report = 1; }
1341
1342	# Print out the header
1343
1344	if ($print_header) {
1345
1346	        # Create column headers with sort links
1347
1348		$source_link  = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Source^$ascend>$heading_1</a>";
1349		$dest_link    = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Dest^$ascend>$heading_2</a>";
1350		$country_link = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Country^$ascend>Country</a>";
1351		$octfl_link   = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^OctFlow^$ascend>Octs/Flow</a>";
1352		$pktfl_link   = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^PktFlow^$ascend>Pkts/Flow</a>";
1353
1354		if ($sampling_multiplier > 0) {
1355			$flows_link   = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Flows^$ascend>Flows*</a>";
1356			$octets_link  = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Octets^$ascend>Octets*</a>";
1357			$packets_link = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Packets^$ascend>Packets*</a>";
1358			$mbps_link    = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Mbps^$ascend>Avg. Rate*</a>";
1359		} else {
1360			$flows_link   = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Flows^$ascend>Flows</a>";
1361			$octets_link  = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Octets^$ascend>Octets</a>";
1362			$packets_link = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Packets^$ascend>Packets</a>";
1363			$mbps_link    = "<a href=$cgi_bin_short/FlowViewer_Sort.cgi?$active_dashboard^$filter_hash^Mbps^$ascend>Avg. Rate</a>";
1364		}
1365
1366		print "<br>\n";
1367		print "<center>\n";
1368		print "<table>\n";
1369		print "<tr>\n";
1370		print "<td align=left>$source_link</td>\n";
1371		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1372		if ($heading_2 ne "") {
1373			print "<td align=left>$dest_link</td>\n";
1374			print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1375		}
1376		print "<td align=right>$flows_link</td>\n";
1377		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1378		print "<td align=right>$octets_link</td>\n";
1379		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1380		print "<td align=right>$packets_link</td>\n";
1381		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1382		if ($rate_report) { print "<td align=right>$mbps_link</td>\n"; }
1383		if ($flow_analysis) {
1384			if ($rate_report) { print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n"; }
1385			print "<td align=right>$octfl_link</td>\n";
1386			print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1387			print "<td align=right>$pktfl_link</td>\n";
1388			if ($country_report) {
1389				print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1390				print "<td align=right>$country_link</td>\n";
1391			}
1392		}
1393		print "</tr>\n";
1394		print "<tr><td>&nbsp&nbsp</td></tr>\n";
1395
1396		print "</b>";
1397
1398		$header_line = "$heading_1 : ";
1399		if ($heading_2 ne "") { $header_line .= "$heading_2 : "; }
1400		$header_line .= "Flows : Octets : Packets";
1401		if ($rate_report) { $header_line .= " : Avg. Rate"; }
1402		if ($flow_analysis) {
1403			$header_line .= " : Octs/Flow : Pkts/Flow";
1404			if ($country_report) { $header_line .= " : Country"; }
1405		}
1406        	print SORTED_SAVE "$header_line\n";
1407
1408		$print_header = 0;
1409	}
1410
1411	# Print out the individual lines
1412
1413	$line_count++;
1414
1415	if (($rate_report) || (($stat_report == 7) && ($IPFIX)) || ($print_report == 14) || ($print_report == 17)) {
1416		if ($IPFIX) {
1417			if ($sort_field == 1) { ($x,$y,$octets,$packets,$flows) = split(/\s+/,$_); }
1418			if ($sort_field == 2) { ($x,$y,$flows,$octets,$packets) = split(/\s+/,$_); }
1419			if ($sort_field == 3) { ($x,$y,$packets,$octets,$flows) = split(/\s+/,$_); }
1420		} else {
1421			($x,$y,$flows,$octets,$packets) = split(/\s+/,$_);
1422		}
1423	} else {
1424		if ($IPFIX) {
1425			if ($sort_field == 1) { ($x,$octets,$packets,$flows) = split(/\s+/,$_); }
1426			if ($sort_field == 2) { ($x,$flows,$octets,$packets) = split(/\s+/,$_); }
1427			if ($sort_field == 3) { ($x,$packets,$octets,$flows) = split(/\s+/,$_); }
1428		} else {
1429			($x,$flows,$octets,$packets)    = split(/\s+/,$_);
1430		}
1431	}
1432
1433        if ($rate_report) {
1434		$flow_rate = int($octets*8/$report_length);
1435		if ($sampling_multiplier > 1) { $flow_rate *= $sampling_multiplier; }
1436		$flow_rate = format_number($flow_rate);
1437	}
1438
1439	# Multiply by sampling multiplier if set
1440
1441	if ($sampling_multiplier > 1) {
1442		$flows     *= $sampling_multiplier;
1443		$octets    *= $sampling_multiplier;
1444		$packets   *= $sampling_multiplier;
1445	}
1446
1447	if ($flow_analysis) {
1448		$oct_per_flow = int($octets / $flows);
1449		$pkt_per_flow = int($packets / $flows);
1450		if ($country_report) { ($as_number,$as_country,$as_name) = dig_as_full($x); }
1451	}
1452
1453	if (($stat_report != 0) && ($octets < $cutoff_octets)) { last; }
1454
1455        # Unit conversion if requested
1456
1457        if ($unit_conversion eq "Y") {
1458             $octets = convert_octets2string($octets);
1459        }
1460
1461	if ($resolve_columns == 1) {
1462                 $x = dig($x);
1463        } elsif ($resolve_columns == 2) {
1464                 $x = dig($x);
1465                 $y = dig($y);
1466        } elsif ($resolve_columns == 3) {
1467                 $x = dig_as($x);
1468        } elsif ($resolve_columns == 4) {
1469                 $x = dig_as($x);
1470                 $y = dig_as($y);
1471        } elsif (($resolve_columns == 5) && ($interface_names)) {
1472                 $x = dig_if($x);
1473        } elsif (($resolve_columns == 6) && ($interface_names)) {
1474                 $x = dig_if($x);
1475                 $y = dig_if($y);
1476        } elsif ($resolve_columns == 7) {
1477                 $x = dig_ex($x);
1478	}
1479
1480	if (($print_report == 12) || ($print_report == 15)) { $x = $x . "/". $sip_prefix_length; }
1481	if (($print_report == 13) || ($print_report == 16)) { $x = $x . "/". $dip_prefix_length; }
1482	if (($print_report == 14) || ($print_report == 17)) { $x = $x . "/". $sip_prefix_length; $y = $y . "/". $dip_prefix_length; }
1483
1484        # Build the line
1485
1486        if ($heading_2 ne "" ) {
1487		$line = $x ." ^ ". $y ." ^ ". $flows ." ^ ". $octets ." ^ ". $packets;
1488        	if ($rate_report) { $line = $line ." ^ ". $flow_rate; }
1489		if ($flow_analysis) { $line .= " ^ ". $oct_per_flow ." ^ ". $pkt_per_flow; }
1490	} elsif (($heading_1 ne "") && ($heading_2 eq "")) {
1491		$line = $x ." ^ ". $flows ." ^ ". $octets ." ^ ". $packets;
1492		if ($flow_analysis)  { $line .= " ^ ". $oct_per_flow ." ^ ". $pkt_per_flow; }
1493		if ($country_report) { $line .= " ^ ". $as_country; }
1494        } elsif ($print_report eq "0") {
1495		$line = sprintf("%-12s %-19s %-19s %-19s", $x, $y, $octets, $flows);
1496		if ($flow_analysis) { $line = sprintf("%-12s %-19s %-19s %-19s %-19s %-19s %-19s", $x, $y, $octets, $flows, $oct_per_flow, $pkt_per_flow, $as_country); }
1497	} else {
1498		$line = $_;
1499	}
1500
1501        if ($line ne "") { print SORTED_SAVE "$line\n"; }
1502
1503	print "<tr>\n";
1504	print "<td align=left>$x</td>\n";
1505	print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1506	if ($heading_2 ne "") {
1507		print "<td align=left>$y</td>\n";
1508		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1509	}
1510	print "<td align=right>$flows</td>\n";
1511	print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1512	print "<td align=right>$octets</td>\n";
1513	print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1514	print "<td align=right>$packets</td>\n";
1515	print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1516	if ($rate_report) { print "<td align=right>$flow_rate</td>\n"; }
1517	if ($flow_analysis) {
1518		if ($rate_report) { print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n"; }
1519		print "<td align=right>$oct_per_flow</td>\n";
1520		print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1521		print "<td align=right>$pkt_per_flow</td>\n";
1522		if ($country_report) {
1523			print "<td>&nbsp&nbsp&nbsp&nbsp&nbsp</td>\n";
1524			print "<td align=right>$as_country</td>\n";
1525		}
1526	}
1527	print "</tr>\n";
1528
1529	if (($stat_report > 0) && ($stat_report != 99)) { if (($line_count+1) > $cutoff_lines) { last; } }
1530}
1531close(SORTED_SAVE);
1532
1533print " <tr><td>&nbsp</td></tr>";
1534print " <tr><td>&nbsp</td></tr>";
1535print " </table>\n";
1536print " </div>\n";
1537
1538&create_UI_service("FlowViewer_Main","service_bottom",$active_dashboard,$filter_hash);
1539&finish_the_page("FlowViewer_Main");
1540
1541# Remove intermediate files
1542
1543$rm_command = "rm $work_directory/FlowViewer_filter_$suffix";
1544if ($debug_files ne "Y") { system($rm_command); }
1545$rm_command = "rm $work_directory/FlowViewer_output_$suffix";
1546if ($debug_files ne "Y") { system($rm_command); }
1547$rm_command = "rm $work_directory/FlowViewer_scanner_$scan_suffix";
1548if ($debug_files ne "Y") { system($rm_command); }
1549
1550# Subroutines
1551
1552sub print_error {
1553
1554	my ($error_text) = @_;
1555	print "  <br>";
1556	print "  $error_text\n";
1557	print " </div>\n";
1558	&create_UI_service("FlowViewer_Main","service_bottom",$active_dashboard,$filter_hash);
1559	&finish_the_page("FlowViewer_Main");
1560	exit;
1561}
1562
1563sub dig {
1564        my ($host_address) = @_;
1565
1566        $host_name = $host_address;
1567
1568        if (defined($host_names{$host_address})) {
1569                $host_name = $host_names{$host_address};
1570                $length_name = length($host_name);
1571                if ($length_name > $dns_column_width) {
1572                        $left_start = $length_name - $dns_column_width;
1573                        $host_name = substr($host_name,$left_start,$dns_column_width);
1574                }
1575        } else {
1576                open(DIG,"$dig $host_address 2>&1|");
1577                $answer_record = 0;
1578                while (<DIG>) {
1579                        chop;
1580                        if (/ANSWER SECTION/) {
1581                                $answer_record = 1;
1582                                next;
1583                        }
1584                        if ($answer_record) {
1585                                ($in_addr,$rec_timeout,$rec_direction,$rec_type,$host_name) = split(/\s+/,$_);
1586                                $last_period = rindex($host_name,"\.");
1587                                $host_name = substr($host_name,0,$last_period);
1588                                $length_name = length($host_name);
1589                                if ($length_name > $dns_column_width) {
1590                                        $left_start = $length_name - $dns_column_width;
1591                                        $host_name = substr($host_name,$left_start,$dns_column_width);
1592                                }
1593                                if (/CNAME/) { $host_name = $host_address; }
1594                                last;
1595                        }
1596                }
1597
1598		if (length($host_name) < 1) { $host_name = $host_address; }
1599		$host_names{$host_address} = $host_name;
1600        }
1601        return $host_name;
1602}
1603
1604sub dig_as {
1605
1606        my ($host_address) = @_;
1607        $as_name = $host_address;
1608
1609        if (defined($as_names{$host_address})) {
1610                $as_name = $as_names{$host_address};
1611        } else {
1612                open(DIG_AS,"dig +short AS$host_address.asn.cymru.com TXT 2>&1|");
1613                $answer_record = 0;
1614                while (<DIG_AS>) {
1615                        chomp;
1616                        if (/[0-9]+ | [A-Z]+ |.*/) {
1617                                s/"//g;
1618                                ($as_number, $as_country, $as_rir, $as_date, $as_name) = split(/ \| /, $_);
1619                                @as_info = split(/\s/, $as_name);
1620                                $as_name = shift(@as_info);
1621                        }
1622                }
1623                if ($as_name eq "") { $as_name = $host_address; }
1624                $as_names{$host_address} = $as_name;
1625        }
1626        return $as_name;
1627}
1628
1629sub dig_as_full {
1630
1631	my ($host_address) = @_;
1632
1633	($a,$b,$c,$d) = split(/\./,$host_address);
1634	$reverse_address = $d .".". $c .".". $b .".". $a;
1635
1636	open(DIG_AS,"dig +short $reverse_address.origin.asn.cymru.com TXT 2>&1|");
1637	while (<DIG_AS>) {
1638		chomp;
1639		if (/[0-9]+ | [A-Z]+ |.*/) {
1640			s/"//g;
1641			($as_number, $ip_range, $as_country, $as_rir, $as_date) = split(/ \| /, $_);
1642		}
1643	}
1644	close (DIG_AS);
1645
1646	if ($as_number =~ / /) { ($as_number,$right_part) = split(/ /,$as_number); }
1647	$as_country = ""; $as_rir = ""; $as_date = ""; $as_name = "";
1648
1649	open(DIG_AS,"dig +short AS$as_number.asn.cymru.com TXT 2>&1|");
1650	while (<DIG_AS>) {
1651		chomp;
1652		if (/[0-9]+ | [A-Z]+ |.*/) {
1653			s/"//g;
1654			($as_number, $as_country, $as_rir, $as_date, $as_name) = split(/ \| /, $_);
1655		}
1656	}
1657	close (DIG_AS);
1658
1659	$as_name = substr($as_name,0,$asn_width);
1660	return ($as_number,$as_country,$as_name);
1661}
1662
1663sub dig_if {
1664
1665	my ($if_number) = @_;
1666	$if_name = $if_number;
1667
1668	if ($device_name ne "") {
1669        	$interfaces_file = "$cgi_bin_directory/NamedInterfaces_Devices";
1670	} elsif ($exporter ne "") {
1671        	$interfaces_file = "$cgi_bin_directory/NamedInterfaces_Exporters";
1672	}
1673
1674	open (NAMED,"<$interfaces_file");
1675	chomp (@interfaces = <NAMED>);
1676	close (NAMED);
1677
1678	foreach $interface (@interfaces) {
1679		if (($interface eq "") || (substr($interface,0,1) eq "#")) { next; }
1680	        ($device,$interface_index,$interface_name) = split(/:/,$interface);
1681	        if (($device eq $device_name) || ($device eq $exporter)) {
1682			if ($interface_index eq $if_number) { $if_name = $interface_name; }
1683			$found_device = 1;
1684		}
1685	}
1686	if ($found_device == 0) { $if_name = "NO_TRANSLATIONS"; }
1687	return $if_name;
1688}
1689
1690sub dig_ex {
1691
1692	my ($exporter_number) = @_;
1693	$exporter_name = $exporter_number;
1694
1695	foreach $exporter (@exporters) {
1696		($exporter_ip,$exp_name) = split(/:/,$exporter);
1697		if ($exporter_number eq $exporter_ip) { $exporter_name = $exp_name; }
1698	}
1699	return $exporter_name;
1700}
1701