]>
Commit | Line | Data |
---|---|---|
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 | ||
27 | use Time::Local; | |
28 | use File::ReadBackwards; | |
29 | use strict; | |
0f14446a AM |
30 | use MIME::Lite; |
31 | ||
db8a01e0 AM |
32 | #use warnings; |
33 | ||
34 | require '/var/ipfire/general-functions.pl'; | |
35 | require "${General::swroot}/accounting/acct-lib.pl"; | |
36 | require "${General::swroot}/lang.pl"; | |
37 | ||
38 | ############# | |
39 | # Variables # | |
40 | ############# | |
41 | ||
42 | my $count = 0; | |
43 | my $dbh; | |
44 | my $logfile = "/var/log/squid/access.log"; | |
45 | my $line = ''; | |
46 | my $checktime = 3600; #1 hour = 3600 sec | |
47 | my $starttime = time; | |
48 | my ($time,$elapsed,$ip,$state,$bytes,$method,$url,$user,$peerstate,$type); #split logfileline into variables | |
49 | my $name; | |
50 | my $name1; | |
51 | my $settingsfile = "${General::swroot}/accounting/settings.conf"; | |
52 | my $proxyenabled = "${General::swroot}/proxy/enable"; | |
53 | my %counter = (); | |
54 | my %counterip = (); | |
55 | my %settings = (); | |
56 | my %toplist = (); | |
57 | my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydat,$isdst)=localtime(); | |
58 | my $skipurlcount=0; | |
59 | my $skipurlsum=0; | |
60 | &General::readhash("$settingsfile", \%settings); | |
61 | my $skipurl=$settings{'SKIPURLS'}; | |
62 | $skipurl="'".$skipurl."'"; | |
63 | my ($mini,$max)=&ACCT::getminmax; | |
64 | my $now = localtime; | |
65 | my $proxylog; | |
66 | my $proxysrv; | |
0f14446a AM |
67 | my $dmafile="${General::swroot}/dma/dma.conf"; |
68 | my $authfile="${General::swroot}/dma/auth.conf"; | |
69 | my $mailfile="${General::swroot}/dma/mail.conf"; | |
70 | my %mail=(); | |
71 | my %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! |
81 | if((! -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 | |
86 | if ((! -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 | |
94 | if (-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"); | |
78af2f67 | 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 | ||
149 | sub 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 | ||
167 | sub 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 | } | |
216 | sub fill_db{ | |
217 | my $tim=time(); | |
218 | #Fill ACCT table with accounting information | |
219 | foreach my $name (sort keys %counter){ | |
78af2f67 | 220 | next if (substr($name,-1,1) eq '$'); |
db8a01e0 AM |
221 | foreach my $bytes (keys %{ $counter{$name} }) { |
222 | $dbh->do("insert into ACCT (TIME_RUN,NAME,BYTES) values ('$tim','$name','$counter{$name}{$bytes}');"); | |
223 | } | |
224 | } | |
225 | } | |
226 | sub sendbill { | |
227 | my $rggrp=$_[0]; | |
228 | my $mwst=$_[1]; | |
229 | my $cur = $_[2]; | |
230 | my @now = localtime(time); | |
231 | $now[5] = $now[5] + 1900; | |
d6413caa | 232 | my $actmonth = $now[4]; |
218d2d75 AM |
233 | my $month; |
234 | $month = '0'.$actmonth if $actmonth < 10; | |
235 | $month = '12' if $actmonth == 0; | |
db8a01e0 | 236 | my $actyear = $now[5]; |
0f14446a | 237 | my ($from,$till)=&ACCT::getmonth($actmonth,$actyear); |
db8a01e0 AM |
238 | my @billar = &ACCT::GetTaValues($from,$till,$rggrp); |
239 | my $address_cust = &ACCT::getTaAddress($rggrp,'CUST'); | |
240 | my $address_host = &ACCT::getTaAddress($rggrp,'HOST'); | |
241 | my $billpos = &ACCT::getextrabillpos($rggrp); | |
242 | my $no = &ACCT::getBillNr; | |
243 | my $back = &ACCT::pdf2(\@billar,$actmonth,$actyear,$mwst,$address_cust,$address_host,$billpos,$rggrp,$cur); | |
244 | 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); | |
245 | ||
246 | foreach my $addrline_cust (@$address_cust){ | |
247 | ($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; | |
248 | } | |
249 | ||
250 | if ($back eq '0'){ | |
251 | &ACCT::logger($settings{'LOG'},"Bill for $company_cust successfully created.\n"); | |
0f14446a | 252 | my $file="/var/ipfire/accounting/bill/$rggrp/$month-$actyear-$no.pdf"; |
db8a01e0 | 253 | $settings{'MAILTXT'} =~ tr/\|/\r\n/ ; |
0f14446a AM |
254 | |
255 | #extract filename from path | |
256 | my ($filename) = $file =~ m{([^/]+)$}; | |
257 | ||
258 | my $msg = MIME::Lite->new( | |
259 | From => $mail{'SENDER'}, | |
260 | To => $email, | |
261 | Cc => $ccmail, | |
262 | Subject => $settings{'MAILSUB'}, | |
263 | Type => 'multipart/mixed' | |
264 | ); | |
265 | ||
266 | $msg->attach( | |
267 | Type => 'TEXT', | |
268 | Data => $settings{'MAILTXT'} | |
269 | ); | |
270 | ||
271 | $msg->attach( | |
272 | Type => 'application/pdf', | |
273 | Path => $file, | |
274 | Filename => $filename, | |
275 | Disposition => 'attachment' | |
276 | ); | |
277 | ||
278 | my $res=$msg->send_by_sendmail; | |
279 | ||
db8a01e0 AM |
280 | if ($res == 0){ |
281 | &ACCT::logger($settings{'LOG'},"Bill for $company_cust successfully sent.\n"); | |
282 | }elsif ($res > 0){ | |
283 | &ACCT::logger($settings{'LOG'},"ERROR: Bill for $company_cust NOT sent.\n"); | |
284 | } | |
285 | return 0; | |
286 | ||
287 | }else{ | |
288 | &ACCT::logger($settings{'LOG'},"ERROR Bill for $company_cust could not be created.\n"); | |
0f14446a AM |
289 | my $msg = MIME::Lite->new( |
290 | From => $mail{'SENDER'}, | |
291 | To => $mail{'RECIPIENT'}, | |
292 | Subject => "ERROR Squid Accounting", | |
293 | Type => 'multipart/mixed' | |
294 | ); | |
295 | ||
296 | $msg->attach( | |
297 | Type => 'TEXT', | |
298 | Data => "The bill could not be created for customer $company_cust" | |
299 | ); | |
300 | ||
301 | $msg->send_by_sendmail; | |
db8a01e0 AM |
302 | return 0; |
303 | } | |
304 | } |