2 # Show a form for selecting a report
4 require './bandwidth-lib.pl';
9 # Validate the bandwidth file
10 if (-d $bandwidth_log) {
11 &ui_print_header(undef, $text{'index_title'}, "", "intro",
13 &ui_print_endpage(&text('index_elog', "<tt>$bandwidth_log</tt>",
14 "../config.cgi?$module_name"));
17 # Validate the bandwidth directory
18 if ($config{'bandwidth_dir'} && !-d $hours_dir) {
19 &ui_print_header(undef, $text{'index_title'}, "", "intro",
21 &ui_print_endpage(&text('index_edir', "<tt>$hours_dir</tt>",
22 "../config.cgi?$module_name"));
25 # Make sure the net and cron modules work
26 foreach $m (split(/\s+/, $module_info{'depends'})) {
27 next if ($m =~ /^[0-9\.]+$/);
28 if (!&foreign_installed($m)) {
29 &ui_print_header(undef, $text{'index_title'}, "", "intro",
31 %minfo = &get_module_info($m);
32 &ui_print_endpage(&text('index_emod', $minfo{'desc'}));
36 # Make sure one of the syslog modules works
37 if (!$syslog_module) {
38 &ui_print_header(undef, $text{'index_title'}, "", "intro",
40 &ui_print_endpage(&text('index_esyslog'));
43 # Check the firewall system
44 if (!$config{'firewall_system'}) {
45 # Try automatic detection
46 $sys = &detect_firewall_system();
48 &ui_print_header(undef, $text{'index_title'}, "", "intro",
50 &ui_print_endpage($text{'index_efiresys'});
52 $config{'firewall_system'} = $sys;
53 &save_module_config();
56 # Is the selected one installed?
57 if (!&check_firewall_system($config{'firewall_system'})) {
58 &ui_print_header(undef, $text{'index_title'}, "", "intro",
60 &ui_print_endpage(&text('index_efiresys2',
61 $text{'system_'.$config{'firewall_system'}},
62 "../config.cgi?$module_name"));
65 &ui_print_header(undef, $text{'index_title'}, "", "intro",
66 1, 1, 0, undef, undef, undef,
67 &text('index_firesys',
68 $text{'system_'.$config{'firewall_system'}},
69 $text{'syslog_'.$syslog_module}));
71 # Make sure the needed firewall rules and syslog entry are in place
72 $missingrule = !&check_rules();
73 if ($syslog_module eq "syslog") {
75 $conf = &syslog::get_config();
76 $sysconf = &find_sysconf($conf);
80 $conf = &syslog_ng::get_config();
81 ($ngdest, $ngfilter, $nglog) = &find_sysconf_ng($conf);
82 $sysconf = $ngdest && $ngfilter && $nglog;
85 if (($missingrule || !$sysconf) && $access{'setup'}) {
86 # Something is missing .. offer to set up
87 print "$text{'index_setupdesc'}\n";
88 if ($missingrule && !$sysconf) {
89 print $text{'index_missing3'};
91 elsif ($missingrule) {
92 print $text{'index_missing2'};
95 print $text{'index_missing1'};
98 print "$text{'index_setupdesc2'}<p>\n";
100 print $iptableserr,"<p>\n";
102 print &ui_form_start("setup.cgi");
103 print "<b>$text{'index_iface'}</b>\n";
104 foreach $i (&net::active_interfaces(), &net::boot_interfaces()) {
105 push(@ifaces, $i->{'fullname'}) if ($i->{'virtual'} eq '' &&
108 print &ui_select("iface", $config{'iface'} || $ifaces[0],
109 [ (map { [ $_, $_ ] } &unique(@ifaces)),
110 [ '', $text{'index_other'} ] ],
111 1, 0, $config{'iface'} ? 1 : 0)." ".
112 &ui_textbox("other", undef, 10);
113 print &ui_submit($text{'index_setup'});
114 print &ui_form_end();
117 elsif ($missingrule || !$sysconf) {
118 print "$text{'index_setupdesc'}\n";
119 print "$text{'index_setupcannot'}<p>\n";
122 # See if any hours have been summarized yet
123 @hours = &list_hours();
125 # Show reporting form
126 print &ui_form_start("index.cgi");
129 print "<tr> <td><b>$text{'index_by'}</b></td>\n";
130 print "<td>",&ui_select("by", $in{'by'},
131 [ [ 'hour', $text{'index_hour'} ],
132 [ 'day', $text{'index_day'} ],
133 [ 'host', $text{'index_host'} ],
134 [ 'proto', $text{'index_proto'} ],
135 [ 'iport', $text{'index_iport'} ],
136 [ 'oport', $text{'index_oport'} ],
137 [ 'port', $text{'index_port'} ] ]),"</td>\n";
139 print "<td><b>$text{'index_for'}</b></td>\n";
140 print "<td>",&ui_select("for", $in{'for'},
141 [ [ '', $text{'index_all'} ],
142 [ 'host', $text{'index_forhost'} ],
143 [ 'proto', $text{'index_forproto'} ],
144 [ 'iport', $text{'index_foriport'} ],
145 [ 'oport', $text{'index_foroport'} ] ]),"\n";
146 print &ui_textbox("what", $in{'for'} ? $in{'what'} : "", 20),
149 print "<tr> <td><b>$text{'index_from'}</b></td>\n";
150 print "<td colspan=4>",
151 &date_input($in{'from_day'}, $in{'from_month'},
152 $in{'from_year'}, "from"),
153 &hourmin_input($in{'from_hour'}, "00", "from"),"</td> </tr>\n";
155 print "<tr> <td><b>$text{'index_to'}</b></td>\n";
156 print "<td colspan=4>",
157 &date_input($in{'to_day'}, $in{'to_month'},
158 $in{'to_year'}, "to"),
159 &hourmin_input($in{'to_hour'}, "00", "to"),"</td> </tr>\n";
165 print "<tr> <td></td> <td colspan=4>\n";
166 print &ui_checkbox("low", 1, $text{'index_low'}, $in{'low'});
167 print &ui_checkbox("resolv", 1, $text{'index_resolv'}, $in{'resolv'});
168 print "</td> </tr>\n";
170 print "<tr> <td colspan=4>",
171 &ui_submit($text{'index_search'}),"</td> </td>\n";
174 print &ui_form_end();
176 elsif (!$missingrule && $sysconf) {
177 print "<b>$text{'index_none'}</b><p>\n";
180 # Find and show any results
182 # Work out the time range, if any
183 &error_setup($text{'index_err'});
184 $fhour = &parse_hour("from");
185 $thour = &parse_hour("to");
187 # First find traffic that matches the 'for' part
188 if ($in{'for'} eq 'host') {
189 if ($in{'what'} =~ /^(\d+)\.(\d+)\.(\d+)\.0$/) {
190 %forhost = map { ("$1.$2.$3.$_", 1) } (0 .. 255);
193 $forhost = &to_ipaddress($in{'what'});
194 $forhost || &error($text{'index_ehost'});
195 $forhost{$forhost}++;
198 elsif ($in{'for'} eq 'proto') {
199 $forproto = uc($in{'what'});
200 $forproto || &error($text{'index_eproto'});
202 elsif ($in{'for'} eq 'iport' || $in{'for'} eq 'oport') {
203 if ($in{'what'} =~ /^\d+$/) {
204 $forportmin = $forportmax = $in{'what'};
206 elsif ($in{'what'} =~ /^(\d+)\-(\d+)$/) {
211 $forportmin = getservbyname($in{'what'}, 'tcp');
212 $forportmin ||= getservbyname($in{'what'}, 'udp');
213 $forportmin || &error($text{'index_eport'});
214 $forportmax = $forportmin;
217 foreach $h (@hours) {
218 next if ($fhour && $h < $fhour);
219 next if ($thour && $h > $thour);
220 $hour = &get_hour($h);
222 # Work out start time for this day
223 @tm = localtime($h*60*60);
224 $thisday = timelocal(0, 0, 0, $tm[3], $tm[4], $tm[5])/(60*60);
226 # Scan all traffic for the hour
227 foreach $k (keys %$hour) {
228 # Skip this count if not relevant
229 ($host, $proto, $iport, $oport) = split(/_/, $k);
231 next if (%forhost && !$forhost{$host});
232 next if ($forproto && $proto ne $forproto);
233 next if ($in{'for'} eq 'iport' &&
234 ($iport < $forportmin || $iport >$forportmax));
235 next if ($in{'for'} eq 'oport' &&
236 ($oport < $forportmin || $oport >$forportmax));
238 # Skip this count if classifying by port and there
240 next if ($in{'by'} eq 'iport' && !$iport ||
241 $in{'by'} eq 'oport' && !$oport ||
242 $in{'by'} eq 'port' && !$iport && !$oport);
244 # Work out a nice service name
245 local ($nsname, $nsoname, $nsiname);
247 if ($in{'by'} eq 'iport') {
248 $nsname = $nsiname = getservbyport($iport, lc($proto));
250 elsif ($in{'by'} eq 'oport') {
251 $nsname = $nsoname = getservbyport($oport, lc($proto));
253 elsif ($in{'by'} eq 'port') {
254 $nsoname = getservbyport($oport, lc($proto));
255 $nsiname = getservbyport($iport, lc($proto));
256 $nsname = $nsoname || $nsiname;
259 # Resolv the hostname
261 if ($in{'resolv'} && $in{'by'} eq 'host') {
262 $resolved = &to_hostname($host);
265 # Skip traffic to high ports, if requested
266 next if ($in{'low'} && $in{'by'} eq 'iport' &&
267 $iport >= 1024 && !$nsname);
268 next if ($in{'low'} && $in{'by'} eq 'oport' &&
269 $oport >= 1024 && !$nsname);
271 # Update the relevant category
272 ($in, $out) = split(/ /, $hour->{$k});
273 if ($in{'by'} eq 'hour') {
274 $count{$h} += $in+$out;
278 elsif ($in{'by'} eq 'day') {
279 $count{$thisday} += $in+$out;
280 $icount{$thisday} += $in;
281 $ocount{$thisday} += $out;
283 elsif ($in{'by'} eq 'host') {
284 $count{$resolved || $host} += $in+$out;
285 $icount{$resolved || $host} += $in;
286 $ocount{$resolved || $host} += $out;
288 elsif ($in{'by'} eq 'proto') {
289 $count{$proto} += $in+$out;
290 $icount{$proto} += $in;
291 $ocount{$proto} += $out;
293 elsif ($in{'by'} eq 'iport') {
294 $count{$nsname || "$proto $iport"} += $in+$out;
295 $icount{$nsname || "$proto $iport"} += $in;
296 $ocount{$nsname || "$proto $iport"} += $out;
298 elsif ($in{'by'} eq 'oport') {
299 $count{$nsname || "$proto $oport"} += $in+$out;
300 $icount{$nsname || "$proto $oport"} += $in;
301 $ocount{$nsname || "$proto $oport"} += $out;
303 elsif ($in{'by'} eq 'port') {
304 if (!$in{'low'} || $oport < 1024 || $nsoname) {
305 $count{$nsoname || "$proto $oport"} += $in;
306 $icount{$nsoname || "$proto $oport"} += $in;
308 if (!$in{'low'} || $iport < 1024 || $nsiname) {
309 $count{$nsiname || "$proto $iport"} += $out;
310 $ocount{$nsiname || "$proto $iport"} += $out;
318 foreach $k (keys %count) {
319 if ($count{$k} > $max) {
325 # Fill in missing hours or days
326 if ($in{'by'} eq 'hour' || $in{'by'} eq 'day') {
327 @order = sort { $b <=> $a } keys %count;
328 $inc = $in{'by'} eq 'hour' ? 1 : 24;
329 $plus = $in{'by'} eq 'hour' ? 0 : 1;
330 for($i=$order[0]; $i>=$order[$#order]; $i-=$inc) {
331 $count{$i} = 0 if (!$count{$i} &&
332 !$count{$i+$plus} && !$count{$i-$plus});
337 if ($in{'by'} eq 'hour' || $in{'by'} eq 'day') {
338 @order = sort { $b <=> $a } keys %count;
341 @order = sort { $count{$b} <=> $count{$a} } keys %count;
343 if ($in{'by'} ne 'hour' && $in{'by'} ne 'day') {
344 @order = grep { $count{$_} } @order;
347 print "<table width=100% cellpadding=0 cellspacing=0>\n";
349 print "<td><b>",$text{'index_h'.$in{'by'}},"</b></td>\n";
350 print "<td colspan=2><b>$text{'index_usage'}</b></td>\n";
353 foreach $k (@order) {
355 if ($in{'by'} eq 'hour') {
356 print "<td>",&make_date($k*60*60),"</td>\n";
358 elsif ($in{'by'} eq 'day') {
359 $date = &make_date_day($k*60*60);
360 print "<td>$date</td>\n";
363 print "<td>$k</td>\n";
366 printf "<img src=images/red.gif width=%d height=10>",
367 $max ? int($width * $icount{$k}/$max)+1 : 1;
368 printf "<img src=images/blue.gif width=%d height=10>",
369 $max ? int($width * $ocount{$k}/$max)+1 : 1;
371 print "<td>",&nice_size($count{$k}),"</td>\n";
372 $total += $count{$k};
375 print "<tr> <td colspan=2></td> <td><b>",
376 &nice_size($total),"</td> </tr>\n";
380 print "<b>$text{'index_nomatch'}</b><p>\n";
384 if (!$missingrule && $sysconf) {
386 print &ui_buttons_start();
388 # Show button to rotate now
389 print &ui_buttons_row("rotate.cgi", $text{'index_rotate'},
390 $text{'index_rotatedesc'});
392 if ($access{'setup'}) {
393 # Show button to turn off reporting
394 print &ui_buttons_row("turnoff.cgi", $text{'index_turnoff'},
395 $text{'index_turnoffdesc'});
398 print &ui_buttons_end();
401 &ui_print_footer("/", $text{'index'});
406 local ($day, $month, $year) =
407 ($in{$pfx."_day"}, $in{$pfx."_month"}-1, $in{$pfx."_year"}-1900);
408 local $hour = $in{$pfx."_hour"};
409 return undef if (!$day);
411 $hour = $pfx eq "from" ? 0 : 23;
414 eval { $tm = timelocal(0, 0, $hour, $day, $month, $year) };
416 &error($text{'index_e'.$pfx});
418 return int($tm/(60*60));
421 # make_date_day(seconds)
422 # Converts a Unix date/time in seconds to a human-readable form
426 @tm = localtime($_[0]);
427 return sprintf "%d/%s/%d",
428 $tm[3], $text{"smonth_".($tm[4]+1)},