pakfire: use correct tree on x86_64.
[ipfire-2.x.git] / src / squid-accounting / acct.pl
CommitLineData
db8a01e0
AM
1#!/usr/bin/perl
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2014 IPFire Team <alexander.marx@ipfire.org> #
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###############################################################################
21
22
23###########
24# Modules #
25###########
26
27use Time::Local;
28use File::ReadBackwards;
29use strict;
0f14446a
AM
30use MIME::Lite;
31
db8a01e0
AM
32#use warnings;
33
34require '/var/ipfire/general-functions.pl';
35require "${General::swroot}/accounting/acct-lib.pl";
36require "${General::swroot}/lang.pl";
37
38#############
39# Variables #
40#############
41
42my $count = 0;
43my $dbh;
44my $logfile = "/var/log/squid/access.log";
45my $line = '';
46my $checktime = 3600; #1 hour = 3600 sec
47my $starttime = time;
48my ($time,$elapsed,$ip,$state,$bytes,$method,$url,$user,$peerstate,$type); #split logfileline into variables
49my $name;
50my $name1;
51my $settingsfile = "${General::swroot}/accounting/settings.conf";
52my $proxyenabled = "${General::swroot}/proxy/enable";
53my %counter = ();
54my %counterip = ();
55my %settings = ();
56my %toplist = ();
57my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydat,$isdst)=localtime();
58my $skipurlcount=0;
59my $skipurlsum=0;
60&General::readhash("$settingsfile", \%settings);
61my $skipurl=$settings{'SKIPURLS'};
62$skipurl="'".$skipurl."'";
63my ($mini,$max)=&ACCT::getminmax;
64my $now = localtime;
65my $proxylog;
66my $proxysrv;
0f14446a
AM
67my $dmafile="${General::swroot}/dma/dma.conf";
68my $authfile="${General::swroot}/dma/auth.conf";
69my $mailfile="${General::swroot}/dma/mail.conf";
70my %mail=();
71my %dma=();
db8a01e0
AM
72
73########
74# Main #
75########
76
77&checkproxy;
78
0f14446a 79
db8a01e0
AM
80#If we have a disabled file and the proxy is off, we don't need to check anything, exit!
81if((! -f $proxyenabled || $proxylog eq $Lang::tr{'stopped'}) && -f "${General::swroot}/accounting/disabled"){
82 &ACCT::logger($settings{'LOG'}," Proxy or proxylogging disabled - exiting with no data collection\n");
83 exit 0;
84}
85#If proxy was turned off within last hour, we need to check missing minutes and write a disabled file
86if ((! -f $proxyenabled || $proxylog eq $Lang::tr{'stopped'}) && ! -f "${General::swroot}/accounting/disabled"){
87 $checktime = (time-$max);
88 open (FH,">${General::swroot}/accounting/disabled");
89 close (FH);
90 &ACCT::logger($settings{'LOG'}," Proxy or proxylogging was disabled during last hour - just checking meantime and disabling data collection\n");
91}
92
93#If proxy is on, we are doing a normal run. maybe we had a disabled file, so delete it here
94if (-f $proxyenabled && $proxylog eq $Lang::tr{'running'}){
95 #check if we are running again after the was shutdown and reenabled
96 if (-f "${General::swroot}/accounting/disabled"){
97 unlink("${General::swroot}/accounting/disabled");
98 }
99 #Find out if the month changed
100 $dbh=&ACCT::connectdb;
101 my $m=sprintf("%d",(localtime((time-3600)))[4]+1);
102 &ACCT::logger($settings{'LOG'},"month before one hour $m, now is ".($mon+1)."\n");
0f14446a 103 if ($m = ($mon+1) || $m == '12' && ($mon+1) == '1'){
db8a01e0
AM
104 #Logrotate
105 my $year1=$year+1900;
106 system ("tar", "cfz", "/var/log/accounting-$m-$year1.tar.gz", "/var/log/accounting.log");
107 unlink ("/var/log/accounting.log");
108 open (FH,">/var/log/accounting.log");
109 close (FH);
110 chmod 0755, "/var/log/accounting.log";
0fa8d28e 111 #move all db entries older than this month to second table and cumulate them daily
db8a01e0
AM
112 &ACCT::movedbdata;
113 &ACCT::logger($settings{'LOG'},"New Month. Old trafficvalues moved to ACCT_HIST Table\n");
0f14446a
AM
114 #check if mail is enabled
115 if ( -f $mailfile){
116 &General::readhash($mailfile, \%mail);
117 }
118 if ($mail{'USEMAIL'} eq 'on'){
db8a01e0
AM
119 &ACCT::logger($settings{'LOG'},"Mailserver is activated - Now sending bills via mail...\n");
120 my $res=&ACCT::getbillgroups;
121 foreach my $line (@$res){
122 my ($grp) = @$line;
0f14446a
AM
123 open (FILE, "<", $dmafile) or die $!;
124 foreach my $line (<FILE>) {
125 $line =~ m/^([A-Z]+)\s+?(.*)?$/;
126 my $key = $1;
127 my $val = $2;
128 $dma{$key}=$val;
129 }
db8a01e0
AM
130 &sendbill($grp,$settings{'MWST'},$settings{'CURRENCY'});
131 }
132 }else{
133 &ACCT::logger($settings{'LOG'},"Mailserver is deactivated - We are NOT sending bills via mail...\n");
134 }
135 }
136
137 &ACCT::logger($settings{'LOG'},"Start reading last hour of access.log\n");
138 &readlog;
139 &fill_db;
140 &ACCT::closedb;
141 $skipurlsum=sprintf("%.2f",$skipurlsum/(1024*1024));
142 &ACCT::logger($settings{'LOG'},"skipped: $skipurlcount Adressen\n");
143 &ACCT::logger($settings{'LOG'},"skipped: $skipurlsum MB\n") if ($skipurl);
144}
145#############
146# functions #
147#############
148
149sub checkproxy{
150 if(-f "${General::swroot}/proxy/enable"){
151 $proxysrv=$Lang::tr{'running'};
152 }else{
153 $proxysrv=$Lang::tr{'stopped'};
154 }
155 my $srce = "${General::swroot}/proxy/squid.conf";
156 my $string1 = 'access\.log';
157 open(FH, $srce);
158 while(my $line = <FH>) {
159 if($line =~ m/$string1/) {
160 $proxylog=$Lang::tr{'running'};
161 }
162 }
163 close FH;
164 return;
165}
166
167sub readlog{
168 my $url1;
169 my $user1;
170 $count = 0;
171 my $urlcnt=0;
172 &ACCT::logger($settings{'LOG'},"Start: $now. Reading data back till: ".localtime(($starttime-$checktime)).".\n");
173 #Open Logfile and begin to read the file backwards
174 my $bw = File::ReadBackwards->new( $logfile ) or die "can't read $logfile $!" ;
175 while( defined( $line = $bw->readline ) ) {
176 undef $url1;
177 chomp $line;
178 #Divide $line into single variables to get timestamp and check if we are within hte desired timerange
179 ($time,$elapsed,$ip,$state,$bytes,$method,$url,$user,$peerstate,$type)=split(m/\s+/, $line);
180 $count += $bytes;
181 $time = substr($time, 0, -4);
182 if (($time > ($starttime-$checktime))){
183 #Skip DENIED stated lines (can be reactivated later)
184 next if ($state =~ m/DENIED/);
185
186 #extract site name
187 if ($url =~ m/([a-z]+:\/\/)??([a-z0-9\-]+\.){1}(([a-z0-9\-]+\.){0,})([a-z0-9\-]+){1}(:[0-9]+)?\/(.*)/o) {
188 $url=$2.$3.$5;
189 } else {
190 my ($a,$b)=split(":",$url);
191 $url=$a;
192 }
193
194 #Skip special URLs like intranet and webservers from local network
195 if ($url =~ m/$skipurl/o) {
196 $skipurlcount++;
197 $skipurlsum+=$bytes;
198 next;
199 };
200
201 #Increase urlcounter
202 $urlcnt++;
203
204 #Get Data for accounting
205 $counter{$user}{'bytes'} += $bytes if ($user ne '-');
206 $counter{$ip}{'bytes'} += $bytes;
207 }else{
208 #If we are out of timewindow, break
209 last;
210 }
211 }
212 $count=sprintf("%.2f",$count/(1024*1024));
213 &ACCT::logger($settings{'LOG'},"got $count MB from $urlcnt URLs this run.\n");
214 $bw->close;
215}
216sub fill_db{
217 my $tim=time();
218 #Fill ACCT table with accounting information
219 foreach my $name (sort keys %counter){
220 foreach my $bytes (keys %{ $counter{$name} }) {
221 $dbh->do("insert into ACCT (TIME_RUN,NAME,BYTES) values ('$tim','$name','$counter{$name}{$bytes}');");
222 }
223 }
224}
225sub sendbill {
226 my $rggrp=$_[0];
227 my $mwst=$_[1];
228 my $cur = $_[2];
229 my @now = localtime(time);
230 $now[5] = $now[5] + 1900;
d6413caa 231 my $actmonth = $now[4];
218d2d75
AM
232 my $month;
233 $month = '0'.$actmonth if $actmonth < 10;
234 $month = '12' if $actmonth == 0;
db8a01e0 235 my $actyear = $now[5];
0f14446a 236 my ($from,$till)=&ACCT::getmonth($actmonth,$actyear);
db8a01e0
AM
237 my @billar = &ACCT::GetTaValues($from,$till,$rggrp);
238 my $address_cust = &ACCT::getTaAddress($rggrp,'CUST');
239 my $address_host = &ACCT::getTaAddress($rggrp,'HOST');
240 my $billpos = &ACCT::getextrabillpos($rggrp);
241 my $no = &ACCT::getBillNr;
242 my $back = &ACCT::pdf2(\@billar,$actmonth,$actyear,$mwst,$address_cust,$address_host,$billpos,$rggrp,$cur);
243 my ($company_cust,$type_cust,$name1_cust,$str_cust,$str_nr_cust,$plz_cust,$city_cust,$bank,$iban,$bic,$blz,$kto,$email,$internet,$hrb,$stnr,$tel_host,$fax_host,$ccmail,$billgrp,$text,$host,$cust,$cent);
244
245 foreach my $addrline_cust (@$address_cust){
246 ($company_cust,$type_cust,$name1_cust,$str_cust,$str_nr_cust,$plz_cust,$city_cust,$bank,$iban,$bic,$blz,$kto,$email,$internet,$hrb,$stnr,$tel_host,$fax_host,$ccmail,$billgrp,$text,$host,$cust,$cent)=@$addrline_cust;
247 }
248
249 if ($back eq '0'){
250 &ACCT::logger($settings{'LOG'},"Bill for $company_cust successfully created.\n");
0f14446a 251 my $file="/var/ipfire/accounting/bill/$rggrp/$month-$actyear-$no.pdf";
db8a01e0 252 $settings{'MAILTXT'} =~ tr/\|/\r\n/ ;
0f14446a
AM
253
254 #extract filename from path
255 my ($filename) = $file =~ m{([^/]+)$};
256
257 my $msg = MIME::Lite->new(
258 From => $mail{'SENDER'},
259 To => $email,
260 Cc => $ccmail,
261 Subject => $settings{'MAILSUB'},
262 Type => 'multipart/mixed'
263 );
264
265 $msg->attach(
266 Type => 'TEXT',
267 Data => $settings{'MAILTXT'}
268 );
269
270 $msg->attach(
271 Type => 'application/pdf',
272 Path => $file,
273 Filename => $filename,
274 Disposition => 'attachment'
275 );
276
277 my $res=$msg->send_by_sendmail;
278
db8a01e0
AM
279 if ($res == 0){
280 &ACCT::logger($settings{'LOG'},"Bill for $company_cust successfully sent.\n");
281 }elsif ($res > 0){
282 &ACCT::logger($settings{'LOG'},"ERROR: Bill for $company_cust NOT sent.\n");
283 }
284 return 0;
285
286 }else{
287 &ACCT::logger($settings{'LOG'},"ERROR Bill for $company_cust could not be created.\n");
0f14446a
AM
288 my $msg = MIME::Lite->new(
289 From => $mail{'SENDER'},
290 To => $mail{'RECIPIENT'},
291 Subject => "ERROR Squid Accounting",
292 Type => 'multipart/mixed'
293 );
294
295 $msg->attach(
296 Type => 'TEXT',
297 Data => "The bill could not be created for customer $company_cust"
298 );
299
300 $msg->send_by_sendmail;
db8a01e0
AM
301 return 0;
302 }
303}