]>
Commit | Line | Data |
---|---|---|
ac1cfefa | 1 | #!/usr/bin/perl |
70df8302 MT |
2 | ############################################################################### |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
75bc929e | 5 | # Copyright (C) 2007-2012 IPFire Team <info@ipfire.org> # |
70df8302 MT |
6 | # # |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
ac1cfefa | 21 | |
75bc929e | 22 | use strict; |
ac1cfefa MT |
23 | |
24 | use Net::IPv4Addr qw( :all ); | |
75bc929e | 25 | use Switch; |
ac1cfefa MT |
26 | |
27 | # enable only the following on debugging purpose | |
1465b127 | 28 | #use warnings; |
cb5e9c6c | 29 | #use CGI::Carp 'fatalsToBrowser'; |
ac1cfefa | 30 | |
986e08d9 | 31 | require '/var/ipfire/general-functions.pl'; |
ac1cfefa MT |
32 | require "${General::swroot}/lang.pl"; |
33 | require "${General::swroot}/header.pl"; | |
34 | ||
c8a8778f MT |
35 | my $colour_multicast = "#A0A0A0"; |
36 | ||
75bc929e MT |
37 | &Header::showhttpheaders(); |
38 | ||
39 | my @network=(); | |
40 | my @masklen=(); | |
41 | my @colour=(); | |
42 | ||
43 | my %netsettings=(); | |
44 | &General::readhash("${General::swroot}/ethernet/settings", \%netsettings); | |
45 | ||
ac1cfefa MT |
46 | #workaround to suppress a warning when a variable is used only once |
47 | my @dummy = ( ${Header::table1colour} ); | |
48 | undef (@dummy); | |
49 | ||
75bc929e MT |
50 | # Read the connection tracking table. |
51 | open(CONNTRACK, "/usr/local/bin/getconntracktable | sort -k 5,5 --numeric-sort --reverse |") or die "Unable to read conntrack table"; | |
52 | my @conntrack = <CONNTRACK>; | |
53 | close(CONNTRACK); | |
ac1cfefa | 54 | |
75bc929e | 55 | # Collect data for the @network array. |
ac1cfefa | 56 | |
75bc929e MT |
57 | # Add Firewall Localhost 127.0.0.1 |
58 | push(@network, '127.0.0.1'); | |
59 | push(@masklen, '255.255.255.255'); | |
60 | push(@colour, ${Header::colourfw}); | |
ac1cfefa | 61 | |
2c42fe6a | 62 | if (open(IP, "${General::swroot}/red/local-ipaddress")) { |
75bc929e MT |
63 | my $redip = <IP>; |
64 | close(IP); | |
65 | ||
66 | chomp $redip; | |
67 | push(@network, $redip); | |
68 | push(@masklen, '255.255.255.255'); | |
69 | push(@colour, ${Header::colourfw}); | |
2c42fe6a MT |
70 | } |
71 | ||
75bc929e MT |
72 | # Add STATIC RED aliases |
73 | if ($netsettings{'RED_DEV'}) { | |
74 | my $aliasfile = "${General::swroot}/ethernet/aliases"; | |
75 | open(ALIASES, $aliasfile) or die 'Unable to open aliases file.'; | |
76 | my @aliases = <ALIASES>; | |
77 | close(ALIASES); | |
78 | ||
79 | # We have a RED eth iface | |
80 | if ($netsettings{'RED_TYPE'} eq 'STATIC') { | |
81 | # We have a STATIC RED eth iface | |
82 | foreach my $line (@aliases) { | |
83 | chomp($line); | |
84 | my @temp = split(/\,/,$line); | |
85 | if ($temp[0]) { | |
86 | push(@network, $temp[0]); | |
87 | push(@masklen, $netsettings{'RED_NETMASK'} ); | |
88 | push(@colour, ${Header::colourfw} ); | |
89 | } | |
90 | } | |
91 | } | |
92 | } | |
ac1cfefa MT |
93 | |
94 | # Add Green Firewall Interface | |
95 | push(@network, $netsettings{'GREEN_ADDRESS'}); | |
96 | push(@masklen, "255.255.255.255" ); | |
97 | push(@colour, ${Header::colourfw} ); | |
98 | ||
99 | # Add Green Network to Array | |
100 | push(@network, $netsettings{'GREEN_NETADDRESS'}); | |
101 | push(@masklen, $netsettings{'GREEN_NETMASK'} ); | |
102 | push(@colour, ${Header::colourgreen} ); | |
103 | ||
104 | # Add Green Routes to Array | |
105 | my @routes = `/sbin/route -n | /bin/grep $netsettings{'GREEN_DEV'}`; | |
106 | foreach my $route (@routes) { | |
75bc929e MT |
107 | chomp($route); |
108 | my @temp = split(/[\t ]+/, $route); | |
109 | push(@network, $temp[0]); | |
110 | push(@masklen, $temp[2]); | |
111 | push(@colour, ${Header::colourgreen} ); | |
5433e2c9 MT |
112 | } |
113 | ||
f9aaffa6 MT |
114 | # Add Blue Firewall Interface |
115 | push(@network, $netsettings{'BLUE_ADDRESS'}); | |
116 | push(@masklen, "255.255.255.255" ); | |
117 | push(@colour, ${Header::colourfw} ); | |
118 | ||
5433e2c9 MT |
119 | # Add Blue Network |
120 | if ($netsettings{'BLUE_DEV'}) { | |
75bc929e MT |
121 | push(@network, $netsettings{'BLUE_NETADDRESS'}); |
122 | push(@masklen, $netsettings{'BLUE_NETMASK'} ); | |
123 | push(@colour, ${Header::colourblue} ); | |
124 | ||
125 | # Add Blue Routes to Array | |
126 | @routes = `/sbin/route -n | /bin/grep $netsettings{'BLUE_DEV'}`; | |
127 | foreach my $route (@routes) { | |
128 | chomp($route); | |
129 | my @temp = split(/[\t ]+/, $route); | |
130 | push(@network, $temp[0]); | |
131 | push(@masklen, $temp[2]); | |
132 | push(@colour, ${Header::colourblue} ); | |
133 | } | |
134 | } | |
135 | ||
5ac2ed47 MT |
136 | # Add Orange Firewall Interface |
137 | push(@network, $netsettings{'ORANGE_ADDRESS'}); | |
138 | push(@masklen, "255.255.255.255" ); | |
139 | push(@colour, ${Header::colourfw} ); | |
140 | ||
75bc929e MT |
141 | # Add Orange Network |
142 | if ($netsettings{'ORANGE_DEV'}) { | |
143 | push(@network, $netsettings{'ORANGE_NETADDRESS'}); | |
144 | push(@masklen, $netsettings{'ORANGE_NETMASK'} ); | |
145 | push(@colour, ${Header::colourorange} ); | |
146 | # Add Orange Routes to Array | |
147 | @routes = `/sbin/route -n | /bin/grep $netsettings{'ORANGE_DEV'}`; | |
148 | foreach my $route (@routes) { | |
149 | chomp($route); | |
150 | my @temp = split(/[\t ]+/, $route); | |
151 | push(@network, $temp[0]); | |
152 | push(@masklen, $temp[2]); | |
153 | push(@colour, ${Header::colourorange} ); | |
154 | } | |
5433e2c9 MT |
155 | } |
156 | ||
c8a8778f MT |
157 | # Highlight multicast connections. |
158 | push(@network, "224.0.0.0"); | |
159 | push(@masklen, "239.0.0.0"); | |
160 | push(@colour, $colour_multicast); | |
161 | ||
6e13d0a5 MT |
162 | # Add OpenVPN net and RED/BLUE/ORANGE entry (when appropriate) |
163 | if (-e "${General::swroot}/ovpn/settings") { | |
75bc929e MT |
164 | my %ovpnsettings = (); |
165 | &General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings); | |
166 | my @tempovpnsubnet = split("\/",$ovpnsettings{'DOVPN_SUBNET'}); | |
167 | ||
168 | # add OpenVPN net | |
169 | push(@network, $tempovpnsubnet[0]); | |
170 | push(@masklen, $tempovpnsubnet[1]); | |
171 | push(@colour, ${Header::colourovpn} ); | |
172 | ||
173 | # add BLUE:port / proto | |
174 | if (($ovpnsettings{'ENABLED_BLUE'} eq 'on') && $netsettings{'BLUE_DEV'}) { | |
175 | push(@network, $netsettings{'BLUE_ADDRESS'} ); | |
176 | push(@masklen, '255.255.255.255' ); | |
177 | push(@colour, ${Header::colourovpn}); | |
178 | } | |
6e13d0a5 | 179 | |
75bc929e MT |
180 | # add ORANGE:port / proto |
181 | if (($ovpnsettings{'ENABLED_ORANGE'} eq 'on') && $netsettings{'ORANGE_DEV'}) { | |
182 | push(@network, $netsettings{'ORANGE_ADDRESS'} ); | |
183 | push(@masklen, '255.255.255.255' ); | |
184 | push(@colour, ${Header::colourovpn} ); | |
185 | } | |
186 | } | |
6e13d0a5 | 187 | |
03435d85 | 188 | open(IPSEC, "${General::swroot}/vpn/config"); |
75bc929e MT |
189 | my @ipsec = <IPSEC>; |
190 | close(IPSEC); | |
7dbf47dc | 191 | |
75bc929e MT |
192 | foreach my $line (@ipsec) { |
193 | my @vpn = split(',', $line); | |
194 | my ($network, $mask) = split("/", $vpn[12]); | |
6e13d0a5 | 195 | |
75bc929e MT |
196 | if (!&General::validip($mask)) { |
197 | $mask = ipv4_cidr2msk($mask); | |
198 | } | |
ac1cfefa | 199 | |
75bc929e MT |
200 | push(@network, $network); |
201 | push(@masklen, $mask); | |
202 | push(@colour, ${Header::colourvpn}); | |
ac1cfefa | 203 | } |
ac1cfefa | 204 | |
d9ac41d5 MT |
205 | if (-e "${General::swroot}/ovpn/n2nconf") { |
206 | open(OVPNN2N, "${General::swroot}/ovpn/ovpnconfig"); | |
207 | my @ovpnn2n = <OVPNN2N>; | |
208 | close(OVPNN2N); | |
209 | ||
210 | foreach my $line (@ovpnn2n) { | |
211 | my @ovpn = split(',', $line); | |
212 | next if ($ovpn[4] ne 'net'); | |
213 | ||
214 | my ($network, $mask) = split("/", $ovpn[12]); | |
215 | if (!&General::validip($mask)) { | |
216 | $mask = ipv4_cidr2msk($mask); | |
217 | } | |
218 | ||
219 | push(@network, $network); | |
220 | push(@masklen, $mask); | |
221 | push(@colour, ${Header::colourovpn}); | |
222 | } | |
223 | } | |
224 | ||
75bc929e MT |
225 | # Show the page. |
226 | &Header::openpage($Lang::tr{'connections'}, 1, ''); | |
227 | &Header::openbigbox('100%', 'left'); | |
228 | &Header::openbox('100%', 'left', $Lang::tr{'connection tracking'}); | |
c2b15814 | 229 | |
75bc929e MT |
230 | # Print legend. |
231 | print <<END; | |
232 | <table width='100%'> | |
233 | <tr> | |
234 | <td align='center'> | |
235 | <b>$Lang::tr{'legend'} : </b> | |
236 | </td> | |
237 | <td align='center' bgcolor='${Header::colourgreen}'> | |
238 | <b><font color='#FFFFFF'>$Lang::tr{'lan'}</font></b> | |
239 | </td> | |
240 | <td align='center' bgcolor='${Header::colourred}'> | |
241 | <b><font color='#FFFFFF'>$Lang::tr{'internet'}</font></b> | |
242 | </td> | |
243 | <td align='center' bgcolor='${Header::colourorange}'> | |
244 | <b><font color='#FFFFFF'>$Lang::tr{'dmz'}</font></b> | |
245 | </td> | |
246 | <td align='center' bgcolor='${Header::colourblue}'> | |
247 | <b><font color='#FFFFFF'>$Lang::tr{'wireless'}</font></b> | |
248 | </td> | |
249 | <td align='center' bgcolor='${Header::colourfw}'> | |
250 | <b><font color='#FFFFFF'>IPFire</font></b> | |
251 | </td> | |
252 | <td align='center' bgcolor='${Header::colourvpn}'> | |
253 | <b><font color='#FFFFFF'>$Lang::tr{'vpn'}</font></b> | |
254 | </td> | |
255 | <td align='center' bgcolor='${Header::colourovpn}'> | |
256 | <b><font color='#FFFFFF'>$Lang::tr{'OpenVPN'}</font></b> | |
257 | </td> | |
c8a8778f MT |
258 | <td align='center' bgcolor='$colour_multicast'> |
259 | <b><font color='#FFFFFF'>Multicast</font></b> | |
260 | </td> | |
75bc929e MT |
261 | </tr> |
262 | </table> | |
263 | <br> | |
264 | END | |
c2b15814 | 265 | |
75bc929e MT |
266 | # Print table header. |
267 | print <<END; | |
268 | <table width='100%'> | |
269 | <tr> | |
270 | <th align='center'> | |
271 | $Lang::tr{'protocol'} | |
272 | </th> | |
273 | <th align='center'> | |
274 | $Lang::tr{'source ip and port'} | |
275 | </th> | |
276 | <th> </th> | |
277 | <th align='center'> | |
278 | $Lang::tr{'dest ip and port'} | |
279 | </th> | |
280 | <th> </th> | |
281 | <th align='center'> | |
282 | $Lang::tr{'download'} / | |
283 | <br>$Lang::tr{'upload'} | |
284 | </th> | |
285 | <th align='center'> | |
286 | $Lang::tr{'connection'}<br>$Lang::tr{'status'} | |
287 | </th> | |
288 | <th align='center'> | |
289 | $Lang::tr{'expires'}<br>($Lang::tr{'seconds'}) | |
290 | </th> | |
291 | </tr> | |
292 | END | |
c2b15814 | 293 | |
75bc929e MT |
294 | foreach my $line (@conntrack) { |
295 | my @conn = split(' ', $line); | |
c2b15814 | 296 | |
75bc929e MT |
297 | # The first bit is the l3 protocol. |
298 | my $l3proto = $conn[0]; | |
c2b15814 | 299 | |
75bc929e MT |
300 | # Skip everything that is not IPv4. |
301 | if ($l3proto ne 'ipv4') { | |
302 | next; | |
303 | } | |
ac1cfefa | 304 | |
75bc929e MT |
305 | # L4 protocol (tcp, udp, ...). |
306 | my $l4proto = $conn[2]; | |
c2b15814 | 307 | |
7d55ca0d | 308 | # Translate unknown protocols. |
75bc929e | 309 | if ($l4proto eq 'unknown') { |
7d55ca0d MT |
310 | my $l4protonum = $conn[3]; |
311 | if ($l4protonum eq '2') { | |
312 | $l4proto = 'IGMP'; | |
313 | } elsif ($l4protonum eq '4') { | |
314 | $l4proto = 'IPv4 Encap'; | |
315 | } elsif ($l4protonum eq '33') { | |
316 | $l4proto = 'DCCP'; | |
317 | } elsif ($l4protonum eq '41') { | |
318 | $l4proto = 'IPv6 Encap'; | |
319 | } elsif ($l4protonum eq '50') { | |
320 | $l4proto = 'ESP'; | |
321 | } elsif ($l4protonum eq '51') { | |
322 | $l4proto = 'AH'; | |
323 | } elsif ($l4protonum eq '132') { | |
324 | $l4proto = 'SCTP'; | |
325 | } else { | |
326 | $l4proto = $l4protonum; | |
327 | } | |
328 | } else { | |
329 | $l4proto = uc($l4proto); | |
75bc929e | 330 | } |
4809e64e | 331 | |
75bc929e MT |
332 | # Source and destination. |
333 | my $sip; | |
c9e01c8c | 334 | my $sip_ret; |
75bc929e | 335 | my $dip; |
c9e01c8c | 336 | my $dip_ret; |
75bc929e | 337 | my $sport; |
c9e01c8c | 338 | my $sport_ret; |
75bc929e | 339 | my $dport; |
c9e01c8c | 340 | my $dport_ret; |
75bc929e MT |
341 | my @packets; |
342 | my @bytes; | |
343 | ||
344 | my $ttl = $conn[4]; | |
345 | my $state; | |
7d55ca0d | 346 | if ($l4proto eq 'TCP') { |
75bc929e MT |
347 | $state = $conn[5]; |
348 | } | |
c2b15814 | 349 | |
75bc929e MT |
350 | # Kick out everything that is not IPv4. |
351 | foreach my $item (@conn) { | |
352 | my ($key, $val) = split('=', $item); | |
353 | ||
354 | switch ($key) { | |
355 | case "src" { | |
c9e01c8c MT |
356 | if ($sip == "") { |
357 | $sip = $val; | |
358 | } else { | |
359 | $dip_ret = $val; | |
360 | } | |
75bc929e MT |
361 | } |
362 | case "dst" { | |
c9e01c8c MT |
363 | if ($dip == "") { |
364 | $dip = $val; | |
365 | } else { | |
366 | $sip_ret = $val; | |
367 | } | |
75bc929e MT |
368 | } |
369 | case "sport" { | |
c9e01c8c MT |
370 | if ($sport == "") { |
371 | $sport = $val; | |
372 | } else { | |
373 | $dport_ret = $val; | |
374 | } | |
75bc929e MT |
375 | } |
376 | case "dport" { | |
c9e01c8c MT |
377 | if ($dport == "") { |
378 | $dport = $val; | |
379 | } else { | |
380 | $sport_ret = $val; | |
381 | } | |
75bc929e MT |
382 | } |
383 | case "packets" { | |
384 | push(@packets, $val); | |
385 | } | |
386 | case "bytes" { | |
387 | push(@bytes, $val); | |
388 | } | |
389 | } | |
390 | } | |
1465b127 | 391 | |
75bc929e MT |
392 | my $sip_colour = ipcolour($sip); |
393 | my $dip_colour = ipcolour($dip); | |
1465b127 | 394 | |
7d55ca0d MT |
395 | my $sserv = ''; |
396 | if ($sport < 1024) { | |
75bc929e | 397 | $sserv = uc(getservbyport($sport, lc($l4proto))); |
7d55ca0d | 398 | } |
1465b127 | 399 | |
7d55ca0d MT |
400 | my $dserv = ''; |
401 | if ($dport < 1024) { | |
75bc929e | 402 | $dserv = uc(getservbyport($dport, lc($l4proto))); |
7d55ca0d | 403 | } |
1465b127 | 404 | |
75bc929e MT |
405 | my $bytes_in = format_bytes($bytes[0]); |
406 | my $bytes_out = format_bytes($bytes[1]); | |
407 | ||
408 | # Format TTL | |
409 | $ttl = format_time($ttl); | |
410 | ||
c9e01c8c MT |
411 | my $sip_extra; |
412 | if ($sip ne $sip_ret) { | |
413 | $sip_extra = "<font color='#FFFFFF'>></font> "; | |
414 | $sip_extra .= "<a href='/cgi-bin/ipinfo.cgi?ip=$sip_ret'>"; | |
415 | $sip_extra .= " <font color='#FFFFFF'>$sip_ret</font>"; | |
416 | $sip_extra .= "</a>"; | |
417 | } | |
418 | ||
419 | my $dip_extra; | |
420 | if ($dip ne $dip_ret) { | |
421 | $dip_extra = "<font color='#FFFFFF'>></font> "; | |
422 | $dip_extra .= "<a href='/cgi-bin/ipinfo.cgi?ip=$dip_ret'>"; | |
423 | $dip_extra .= " <font color='#FFFFFF'>$dip_ret</font>"; | |
424 | $dip_extra .= "</a>"; | |
425 | } | |
426 | ||
427 | ||
428 | my $sport_extra; | |
429 | if ($sport ne $sport_ret) { | |
430 | my $sserv_ret = ''; | |
431 | if ($sport_ret < 1024) { | |
432 | $sserv_ret = uc(getservbyport($sport_ret, lc($l4proto))); | |
433 | } | |
434 | ||
435 | $sport_extra = "<font color='#FFFFFF'>></font> "; | |
436 | $sport_extra .= "<a href='http://isc.sans.org/port_details.php?port=$sport_ret' target='top' title='$sserv_ret'>"; | |
437 | $sport_extra .= " <font color='#FFFFFF'>$sport_ret</font>"; | |
438 | $sport_extra .= "</a>"; | |
439 | } | |
440 | ||
441 | my $dport_extra; | |
442 | if ($dport ne $dport_ret) { | |
443 | my $dserv_ret = ''; | |
444 | if ($dport_ret < 1024) { | |
445 | $dserv_ret = uc(getservbyport($dport_ret, lc($l4proto))); | |
446 | } | |
447 | ||
448 | $dport_extra = "<font color='#FFFFFF'>></font> "; | |
449 | $dport_extra .= "<a href='http://isc.sans.org/port_details.php?port=$dport_ret' target='top' title='$dserv_ret'>"; | |
450 | $dport_extra .= " <font color='#FFFFFF'>$dport_ret</font>"; | |
451 | $dport_extra .= "</a>"; | |
452 | } | |
453 | ||
75bc929e MT |
454 | print <<END; |
455 | <tr> | |
456 | <td align='center'>$l4proto</td> | |
457 | <td align='center' bgcolor='$sip_colour'> | |
458 | <a href='/cgi-bin/ipinfo.cgi?ip=$sip'> | |
459 | <font color='#FFFFFF'>$sip</font> | |
460 | </a> | |
c9e01c8c | 461 | $sip_extra |
75bc929e MT |
462 | </td> |
463 | <td align='center' bgcolor='$sip_colour'> | |
c9e01c8c MT |
464 | <a href='http://isc.sans.org/port_details.php?port=$sport' target='top' title='$sserv'> |
465 | <font color='#FFFFFF'>$sport</font> | |
75bc929e | 466 | </a> |
c9e01c8c | 467 | $sport_extra |
75bc929e MT |
468 | </td> |
469 | <td align='center' bgcolor='$dip_colour'> | |
470 | <a href='/cgi-bin/ipinfo.cgi?ip=$dip'> | |
471 | <font color='#FFFFFF'>$dip</font> | |
472 | </a> | |
c9e01c8c | 473 | $dip_extra |
75bc929e MT |
474 | </td> |
475 | <td align='center' bgcolor='$dip_colour'> | |
c9e01c8c MT |
476 | <a href='http://isc.sans.org/port_details.php?port=$dport' target='top' title='$dserv'> |
477 | <font color='#FFFFFF'>$dport</font> | |
75bc929e | 478 | </a> |
c9e01c8c | 479 | $dport_extra |
75bc929e MT |
480 | </td> |
481 | <td align='center'> | |
482 | $bytes_in / $bytes_out | |
483 | </td> | |
484 | <td align='center'>$state</td> | |
485 | <td align='center'>$ttl</td> | |
486 | </tr> | |
ac1cfefa | 487 | END |
ac1cfefa | 488 | } |
c2b15814 | 489 | |
75bc929e MT |
490 | # Close the main table. |
491 | print "</table>"; | |
ac1cfefa MT |
492 | |
493 | &Header::closebox(); | |
494 | &Header::closebigbox(); | |
495 | &Header::closepage(); | |
496 | ||
75bc929e MT |
497 | sub format_bytes($) { |
498 | my $bytes = shift; | |
499 | my @units = ("B", "k", "M", "G", "T"); | |
500 | ||
501 | foreach my $unit (@units) { | |
502 | if ($bytes < 1024) { | |
503 | return sprintf("%d%s", $bytes, $unit); | |
504 | } | |
c2b15814 | 505 | |
75bc929e MT |
506 | $bytes /= 1024; |
507 | } | |
508 | ||
509 | return sprintf("%d%s", $bytes, $units[$#units]); | |
c2b15814 MT |
510 | } |
511 | ||
75bc929e MT |
512 | sub format_time($) { |
513 | my $time = shift; | |
c2b15814 | 514 | |
75bc929e MT |
515 | my $seconds = $time % 60; |
516 | my $minutes = $time / 60; | |
c2b15814 | 517 | |
75bc929e MT |
518 | my $hours = 0; |
519 | if ($minutes >= 60) { | |
520 | $hours = $minutes / 60; | |
521 | $minutes %= 60; | |
522 | } | |
523 | ||
524 | return sprintf("%3d:%02d:%02d", $hours, $minutes, $seconds); | |
c2b15814 MT |
525 | } |
526 | ||
75bc929e MT |
527 | sub ipcolour($) { |
528 | my $id = 0; | |
529 | my $colour = ${Header::colourred}; | |
530 | my ($ip) = $_[0]; | |
531 | my $found = 0; | |
532 | ||
533 | foreach my $line (@network) { | |
534 | if ($network[$id] eq '') { | |
535 | $id++; | |
536 | } else { | |
537 | if (!$found && ipv4_in_network($network[$id], $masklen[$id], $ip) ) { | |
538 | $found = 1; | |
539 | $colour = $colour[$id]; | |
540 | } | |
541 | $id++; | |
542 | } | |
543 | } | |
544 | ||
545 | return $colour; | |
c2b15814 MT |
546 | } |
547 | ||
548 | 1; |