]> git.ipfire.org Git - ipfire-2.x.git/blame - src/wio/main/wio.pl
BUG 11487:solve problem with unexspected shutdown
[ipfire-2.x.git] / src / wio / main / wio.pl
CommitLineData
0d6cc79d
SF
1#!/usr/bin/perl
2#
3###############################################################################
4# #
5# IPFire.org - A linux based firewall #
a25c95b3 6# Copyright (C) 2017-2018 Stephan Feddersen <sfeddersen@ipfire.org> #
0d6cc79d
SF
7# All Rights Reserved. #
8# #
9# This program is free software: you can redistribute it and/or modify #
10# it under the terms of the GNU General Public License as published by #
11# the Free Software Foundation, either version 3 of the License, or #
12# (at your option) any later version. #
13# #
14# This program is distributed in the hope that it will be useful, #
15# but WITHOUT ANY WARRANTY; without even the implied warranty of #
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
17# GNU General Public License for more details. #
18# #
19# You should have received a copy of the GNU General Public License #
20# along with this program. If not, see <http://www.gnu.org/licenses/>. #
21# #
22###############################################################################
23#
2a1c1735 24# Version: 2019/06/04 21:12:23
0d6cc79d
SF
25#
26# This wio.pl is based on the Code from the IPCop WIO Addon
27# and is extremly adapted to work with IPFire.
28#
29# Autor: Stephan Feddersen
30# Co-Autor: Alexander Marx
31# Co-Autor: Frank Mainz
32#
33
34# enable only the following on debugging purpose
35#use warnings;
36
37use strict;
38use POSIX qw(strftime);
39use Time::HiRes qw(gettimeofday tv_interval);
40use Net::Ping;
41use RRDs;
42use Fatal qw/ open /;
43
44require '/var/ipfire/general-functions.pl';
45require '/var/ipfire/lang.pl';
46require '/usr/lib/wio/wio-lib.pl';
47
48my ( $debug, $i, $t, $ib, $tb, $ivpn, $tvpn ) = '';
49my $logdir = "/var/log/wio";
50my $owner = getpwnam "nobody";
51my $group = getgrnam "nobody";
52my $ipadrfile = "$logdir/wioips";
53
54unless ( -e $ipadrfile ) { print ( "The file $ipadrfile doesn't exist!\n" ); exit; }
55
56foreach (@ARGV) {
57 if ( $_ eq '-d' || $_ eq '--debug') { $debug = 1; }
58 if ( $_ eq '-h' || $_ eq '--help' ) { die help(); }
59}
60
61my ( %wiosettings, %mainsettings, %mailsettings, %netsettings ) = ();
62
63&General::readhash('/var/ipfire/main/settings', \%mainsettings);
64&General::readhash('/var/ipfire/ethernet/settings', \%netsettings);
65&General::readhash('/var/ipfire/dma/mail.conf', \%mailsettings);
66&General::readhash("/var/ipfire/wio/wio.conf", \%wiosettings);
67
68my $now = strftime "%a, %d.%m.%Y %H:%M:%S", localtime;
69my $logging = $wiosettings{'LOGGING'};
70my $mailstyle = $wiosettings{'MAILSTYLE'};
71my $mailremark = $wiosettings{'MAILREMARK'};
72my $timeout = $wiosettings{'TIMEOUT'};
73my $shutdown = $wiosettings{'SHUTDOWN'};
74my $rrddir = "/var/log/rrd/wio";
75my $onoffip = "$logdir/wioscip";
76my $hostname = "$mainsettings{'HOSTNAME'}.$mainsettings{'DOMAINNAME'}";
77my $redactive = "/var/ipfire/red/active";
78my $rediface = "/var/ipfire/red/iface";
79my $reddev = '';
80
81if ( -e $rediface ) {
82 $reddev = &General::get_red_interface;
83}
84
85my $redip = $hostname;
86my $vpnpid = ( -e "/var/run/charon.pid" ? `awk '{print $1}' /var/run/charon.pid`: '');
87my $ovpnpid = ( -e "/var/run/openvpn.pid" ? `awk '{print $1}' /var/run/openvpn.pid`: '');
88
2a1c1735
SF
89my $steptime = $wiosettings{'CRON'} *= 60;
90my $i_ping = 'icmp';
91my $t_ping = 'tcp';
0d6cc79d
SF
92
93my $nr = 1;
94my $poweroff = 0;
95
96my ( $togglestat, $arp, $time, $start, $timestamp ) = 0;
97my ( $id, $ipadr, $ipadrnew, $host, $hostnew, $enable, $remark, $dyndns, $dyndnsip ) = '';
98my ( $mail, $mailon, $mailoff, $ping, $on, $httphost, $mailen ) = '';
99my ( $msg, $logmsg, $mailmsg, $smailtxt, $infomsg, $client, $mode, $onbak, $arpclient ) = '';
100my ( $ping_i, $ping_t, $ping_ib, $ping_tb, $ping_iv, $ping_tv, $pingmode ) = '';
101my ( @tmp, @arptmp, @myarray, @status, @arpclients ) = '';
102my @ifaces = ('GREEN','BLUE','ORANGE');
103
0d6cc79d
SF
104if ( $mailsettings{'USEMAIL'} eq 'on' ) { $mailen = 'on'; }
105else { $mailen = 'off'; }
106
107if ( -e $redactive ) {
108 open(IPADDR, "/var/ipfire/red/local-ipaddress");
109 $redip = <IPADDR>;
110 close IPADDR;
111 chomp($redip);
112}
113
114if ($debug) {
115 $start = [gettimeofday];
116 startdebug();
117}
118
119foreach (@ifaces) {
120 if ( $netsettings{"${_}_DEV"} ne '' && $netsettings{"${_}_DEV"} ne 'disabled' ) {
121 my $output = `ifconfig $netsettings{"${_}_DEV"}`;
122
123 if ( grep (/RX bytes:0/, $output) ) { next; }
124 else {
125 @arptmp = `/usr/local/bin/wioscan -s $netsettings{"${_}_DEV"}`;
126
127 foreach $arpclient (@arptmp) {
128 push (@arpclients, (split (/\,/,$arpclient))[1]);
129 }
130 }
131 $output = '';
132 undef(@arptmp);
133 }
134}
135
136if ( -e "$onoffip" ) { open( FILE, "< $onoffip" ); }
137else { open( FILE, "< $ipadrfile" ); }
138@myarray = <FILE>;
139close(FILE);
140
141# ping all clients
142
143foreach (@myarray) {
144 chomp;
145 @tmp = split( /\,/, $_ );
146
147 ($id,$timestamp,$ipadr,$host,$enable,$remark,$dyndns,$mailon,$mailoff,$ping,$on,$httphost) = @tmp;
148
149 $timestamp = strftime "%d.%m.%Y - %H:%M:%S", localtime;
150
151 if ( $enable ne 'on' ) {
152 push (@status, "$id,$timestamp,$ipadr,$host,$enable,$remark,$dyndns,$mailon,$mailoff,$ping,$on,$httphost\n");
153 next;
154 }
155
156 if ( defined($dyndns) && ( $dyndns =~ 'on' ) ) {
157 ($dyndnsip, $infomsg) = &WIO::getdyndnsip($host, @myarray);
158 if ($dyndnsip ne $ipadr) { $ipadr = $dyndnsip; }
159 }
160
161 $ping_i = $ping_t = $ping_ib = $ping_tb = $ping_iv = $ping_tv = $pingmode = $arp = 0;
162
163 foreach (@arpclients) {
164 chomp;
165 unless ( $ipadr eq $_ )
166 {
167 $i = Net::Ping->new( $i_ping, $timeout );
168 unless ( defined $i ) { die "Can't create Net::Ping object $!"; }
169
170 $t = Net::Ping->new( $t_ping, $timeout );
171 unless ( defined $t ) { die "Can't create Net::Ping object $!"; }
172
173 $ib = Net::Ping->new( $i_ping, $timeout );
174 unless ( defined $ib ) { die "Can't create Net::Ping object $!"; }
175 $ib->bind($redip);
176
177 $tb = Net::Ping->new( $t_ping, $timeout );
178 unless ( defined $tb ) { die "Can't create Net::Ping object $!"; }
179 $tb->bind($redip);
180
181 if ($ovpnpid || $vpnpid)
182 {
183 $ivpn = Net::Ping->new( $i_ping, $timeout );
184 unless ( defined $ivpn ) { die "Can't create Net::Ping object $!"; }
185 $ivpn->bind($hostname);
186
187 $tvpn = Net::Ping->new( $t_ping, $timeout );
188 unless ( defined $tvpn ) { die "Can't create Net::Ping object $!"; }
189 $tvpn->bind($hostname);
190 }
191 }
192 else { $arp = 1 }
193 }
194
195 $client = ( ( $dyndns eq 'on' || $ping eq 'fqdn' ) ? $host : $ipadr );
196
197 if ($debug) {
198 printf "%2s %15s", $nr++, ($client ne $ipadr ? $ipadr : $client );
199 $time = [gettimeofday];
200 }
201
202 if ( $arp == 1
203 || ($ping_i = $i->ping($client))
204 || ($ping_t = $t->ping($client))
205 || ($ping_ib = $ib->ping($client))
206 || ($ping_tb = $tb->ping($client))
207 || ($ovpnpid?($ping_iv = $ivpn->ping($client)) : 0)
208 || ($vpnpid?($ping_tv = $tvpn->ping($client)) : 0) )
209 {
210 $mode = 100;
211 $msg = "$Lang::tr{'wio up'}";
212 $onbak = $on;
213 $togglestat = ( $on ne 'on' ) ? 1 : 0;
214 $on = 'on';
215 }
216 else {
217 $mode = 0;
218 $msg = "$Lang::tr{'wio down'}";
219 $onbak = $on;
220 $togglestat = ( $on ne 'off' ) ? 1 : 0;
221 $on = 'off';
222 }
223
224 push (@status, "$id,$timestamp,$ipadr,$host,$enable,$remark,$dyndns,$mailon,$mailoff,$ping,$on,$httphost\n");
225
226 if ($debug) {
227 $mail = '----';
228 if ( $mailon eq 'on' && $togglestat == 1 && $mode == 100 ) { $mail = 'Online'; }
229 if ( $mailoff eq 'on' && $togglestat == 1 && $mode == 0 ) { $mail = 'Offline'; }
230 if ( $dyndns ne 'on' ) { $dyndns = 'off'; }
231
232 $pingmode = $arp ? 'ARPSCAN' : $ping_i ? 'ICMP' : $ping_t ? 'TCP' : $ping_ib ? 'ICMP+BIND' : $ping_tb ? 'TCP+BIND' : $ping_iv ? 'VPN ICMP' : $ping_tv ? 'VPN TCP' : 'NO ECHO';
233 printf "%7s%8s%9s%10s %.4f sek%12s\n", $ping, $dyndns, $msg, $mail, tv_interval($time), $pingmode;
234 }
235
236 if ( $host eq '' ) { $hostnew = 'n/a'; } else { $hostnew = $host; }
237 if ( $ipadr eq '' ) { $ipadrnew = 'n/a'; } else { $ipadrnew = $ipadr; }
238
239 if ( $logging eq 'on' ) {
240 $logmsg = "Client: $hostnew - IP: $ipadrnew - Status: $msg";
241 &General::log("wio","$logmsg");
242 }
243
244 if ( $mailen eq 'on' && $togglestat == 1 && ($mailon eq 'on' || $mailoff eq 'on')) {
245
246 if ( $mailstyle eq 'email' || ($mailstyle eq 'smail' && $smailtxt eq '') ) { $mailmsg .= "Date\t : $now\n\n"; }
247
248 $mailmsg .= "Client\t : $hostnew\nIP\t : $ipadrnew\nStatus\t : $msg\n";
249
250 if ( $mailremark eq 'on' && $remark ne '' ) {
251 $mailmsg .= "Remark : $remark\n\n";
252 }
253
254 if ( $mailstyle eq 'email' ) {
255 &WIO::mailsender("WIO - $host - $msg", $mailmsg);
256 undef ($mailmsg);
257 }
258 elsif ( $mailstyle eq 'smail' ) {
259 $smailtxt .= $mailmsg."\n";
260 undef ($mailmsg);
261 }
262 }
263
264 if ( $ping ne 'fqdn' ) { $client = $host; }
265 if ( $host eq '' ) { $client = $ipadr; }
266
267 updatewiodata("$id");
268
269 if ( $arp == 0 ) {
270 $i->close();
271 $t->close();
272 $ib->close();
273 $tb->close();
274 }
275
276 if ( ( -e $ovpnpid || -e $vpnpid ) && $arp == 0 ) {
277 $ivpn->close();
278 $tvpn->close();
279 }
280}
281
282# write adressfile new
283
284if ( !-e $onoffip ) {
285 open( FILE, "> $ipadrfile" );
286 print FILE @status;
287 close(FILE);
288}
289else {
290 system("/bin/sed -i 's#$tmp[0],$tmp[1],$tmp[2],$tmp[3],$tmp[4],$tmp[5],$tmp[6],$tmp[7],$tmp[8],$tmp[9],$tmp[10],$tmp[11]#$id,$timestamp,$ipadr,$host,$enable,$remark,$dyndns,$mailon,$mailoff,$ping,$on,$httphost#g' $ipadrfile");
291 chmod ( 0644, $ipadrfile );
292 chown ( $owner, $group, $ipadrfile );
293}
294
295if ($debug) {
296 printf ("\n$Lang::tr{'wio_scriptruntime'}: %.4f $Lang::tr{'age ssecond'}\n\n", tv_interval($start));
297}
298
299if ( $smailtxt ne '' ) { &WIO::mailsender($Lang::tr{'wio_sub'}, $smailtxt); }
300
2a1c1735 301if ($shutdown eq 'on' && ! -e $onoffip) {
0d6cc79d
SF
302 foreach (@status) {
303 chomp;
304 @tmp = split( /\,/, $_ );
305
306 ($id,$timestamp,$ipadr,$host,$enable,$remark,$dyndns,$mailon,$mailoff,$ping,$on,$httphost) = @tmp;
307
308 if ( $on eq 'on' ) {
309 $poweroff = 0;
310 last;
311 }
312 else {
313 $poweroff = 1;
314 next;
315 }
316 }
317
318 if ($poweroff == 1) {
319 if ($debug) {
320 printf "$Lang::tr{'shutting down ipfire'}!\n\n";
321 }
322
323 &General::log("wio","$Lang::tr{'shutting down ipfire'}!");
324 system '/usr/local/bin/ipfirereboot down';
325 }
326}
327
328undef (@tmp);
329undef (@myarray);
330undef (@status);
331undef (@arptmp);
332undef (@arpclients);
333
334if ( -e $onoffip ) { unlink($onoffip); }
335
336sub updatewiodata {
337 my $id = $_[0];
338
339 if ( !-e "$rrddir/$id.rrd" ) {
340 RRDs::create(
341 "$rrddir/$id.rrd", "--step=$steptime",
342 "DS:mode:GAUGE:3600:0:100", "RRA:AVERAGE:0.5:1:576",
343 "RRA:AVERAGE:0.5:6:672", "RRA:AVERAGE:0.5:24:732",
344 "RRA:AVERAGE:0.5:144:1460"
345 );
346 my $ERROR = RRDs::error;
347 print "Error in RRD::create for Who Is Online: $ERROR\n" if $ERROR;
348 }
349
350 RRDs::update( "$rrddir/$id.rrd", "-t", "mode", "N:$mode" );
351
352 my $error = RRDs::error;
353
354 if ($error) { &General::log("wio","$error"); }
355}
356
357sub startdebug {
358
359printf "
360HOSTNAME : $hostname
361TIMEOUT : $timeout $Lang::tr{'age ssecond'}
362MAILSTYLE : $mailstyle
363RED TYPE : $netsettings{'RED_TYPE'}
364RED DEVICE : $reddev
365RED ADDRESS : $redip
366SHUTDOWN : $shutdown
367";
368 if ($ovpnpid) {printf "OVPN PID : $ovpnpid"}
369 if ($vpnpid) {printf "VPN PID : $vpnpid"}
370printf "
371$Lang::tr{'wio_search'}
372
373%3s%17s%7s%8s%9s%10s%15s%12s
374---------------------------------------------------------------------------------
375","ID ", "$Lang::tr{'wio ipadress'}", "Ping", "DynDNS", "Status", "Mail", "$Lang::tr{'wio_answer_time'}", "$Lang::tr{'wio_answer'}";
376}
377
378sub help {
379 return "
380Who Is Online? for IPFire
381
382use option -d for debugging
383use option -h for help\n\n";
384}