1package Classes::UPNP::AVM::FritzBox7390;
2our @ISA = qw(Classes::UPNP::AVM);
3use strict;
4
5{
6  our $sid = undef;
7}
8
9sub sid : lvalue {
10  my ($self) = @_;
11  $Classes::UPNP::AVM::FritzBox7390::sid;
12}
13
14sub init {
15  my ($self) = @_;
16  foreach my $module (qw(HTML::TreeBuilder LWP::UserAgent Encode Digest::MD5 JSON)) {
17    if (! eval "require $module") {
18      $self->add_unknown("could not find $module module");
19    }
20  }
21  if (! $self->check_messages()) {
22    if ($self->mode =~ /device::hardware::health/) {
23      $self->login();
24      $self->analyze_environmental_subsystem();
25      $self->check_environmental_subsystem();
26    } elsif ($self->mode =~ /device::hardware::load/) {
27      $self->login();
28      $self->analyze_cpu_subsystem();
29      $self->check_cpu_subsystem();
30    } elsif ($self->mode =~ /device::hardware::memory/) {
31      $self->login();
32      $self->analyze_mem_subsystem();
33      $self->check_mem_subsystem();
34    } elsif ($self->mode =~ /device::interfaces/) {
35      $self->analyze_and_check_interface_subsystem("Classes::UPNP::AVM::FritzBox7390::Component::InterfaceSubsystem");
36    } elsif ($self->mode =~ /device::smarthome/) {
37      $self->login();
38      $self->analyze_and_check_smarthome_subsystem("Classes::UPNP::AVM::FritzBox7390::Component::SmartHomeSubsystem");
39    } else {
40      $self->no_such_mode();
41    }
42    $self->logout();
43  }
44}
45
46sub login {
47  my ($self) = @_;
48  my $ua = LWP::UserAgent->new;
49  my $loginurl = sprintf "http://%s/login_sid.lua", $self->opts->hostname;
50  my $resp = $ua->get($loginurl);
51  my $content = $resp->content();
52  my $challenge = ($content =~ /<Challenge>(.*?)<\/Challenge>/ && $1);
53  my $input = $challenge . '-' . $self->opts->community;
54  Encode::from_to($input, 'ascii', 'utf16le');
55  my $challengeresponse = $challenge . '-' . lc(Digest::MD5::md5_hex($input));
56  $resp = HTTP::Request->new(POST => $loginurl);
57  $resp->content_type("application/x-www-form-urlencoded");
58  my $login = "response=$challengeresponse";
59  if ($self->opts->username) {
60      $login .= "&username=" . $self->opts->username;
61  }
62  $resp->content($login);
63  my $loginresp = $ua->request($resp);
64  $content = $loginresp->content();
65  $self->sid() = ($content =~ /<SID>(.*?)<\/SID>/ && $1);
66  if (! $loginresp->is_success() || ! $self->sid() || $self->sid() =~ /^0+$/) {
67    $self->add_critical($loginresp->status_line());
68  } else {
69    $self->debug("logged in with sid ".$self->sid());
70  }
71}
72
73sub logout {
74  my ($self) = @_;
75  return if ! $self->sid();
76  my $ua = LWP::UserAgent->new;
77  my $loginurl = sprintf "http://%s/login_sid.lua", $self->opts->hostname;
78  my $resp = HTTP::Request->new(POST => $loginurl);
79  $resp->content_type("application/x-www-form-urlencoded");
80  my $logout = "sid=".$self->sid()."&security:command/logout=1";
81  $resp->content($logout);
82  my $logoutresp = $ua->request($resp);
83  $self->sid() = undef;
84  $self->debug("logged out");
85}
86
87sub DESTROY {
88  my ($self) = @_;
89  $self->logout();
90}
91
92sub http_get {
93  my ($self, $page) = @_;
94  my $ua = LWP::UserAgent->new;
95  if ($page =~ /\?/) {
96    $page .= "&sid=".$self->sid();
97  } else {
98    $page .= "?sid=".$self->sid();
99  }
100  my $url = sprintf "http://%s/%s", $self->opts->hostname, $page;
101  $self->debug("http get ".$url);
102  my $resp = $ua->get($url);
103  if (! $resp->is_success()) {
104    $self->add_critical($resp->status_line());
105  } else {
106  }
107  return $resp->content();
108}
109
110sub analyze_cpu_subsystem {
111  my ($self) = @_;
112  my $html = $self->http_get('system/ecostat.lua');
113  if ($html =~ /uiSubmitLogin/) {
114    $self->add_critical("wrong login");
115    $self->{cpu_usage} = 0;
116  } elsif ($html =~ /StatCPU/) {
117    my $cpu = (grep /StatCPU/, split(/\n/, $html))[0];
118    my @cpu = ($cpu =~ /= "(.*?)"/ && split(/,/, $1));
119    $self->{cpu_usage} = $cpu[0];
120  } elsif ($html =~ /uiViewCpu/) {
121    $html =~ /Query1 = "(.*?)"/;
122    $self->{cpu_usage} = (split(",", $1))[0];
123  }
124}
125
126sub analyze_mem_subsystem {
127  my ($self) = @_;
128  my $html = $self->http_get('system/ecostat.lua');
129  if ($html =~ /uiSubmitLogin/) {
130    $self->add_critical("wrong login");
131    $self->{ram_used} = 0;
132  } elsif ($html =~ /StatRAMCacheUsed/) {
133    my $ramcacheused = (grep /StatRAMCacheUsed/, split(/\n/, $html))[0];
134    my @ramcacheused = ($ramcacheused =~ /= "(.*?)"/ && split(/,/, $1));
135    $self->{ram_cache_used} = $ramcacheused[0];
136    my $ramphysfree = (grep /StatRAMPhysFree/, split(/\n/, $html))[0];
137    my @ramphysfree = ($ramphysfree =~ /= "(.*?)"/ && split(/,/, $1));
138    $self->{ram_phys_free} = $ramphysfree[0];
139    my $ramstrictlyused = (grep /StatRAMStrictlyUsed/, split(/\n/, $html))[0];
140    my @ramstrictlyused = ($ramstrictlyused =~ /= "(.*?)"/ && split(/,/, $1));
141    $self->{ram_strictly_used} = $ramstrictlyused[0];
142    $self->{ram_used} = $self->{ram_strictly_used} + $self->{ram_cache_used};
143  } elsif ($html =~ /uiViewRamValue/) {
144    $html =~ /Query1 ="(.*?)"/;
145    $self->{ram_free} = (split(",", $1))[0];
146    $html =~ /Query2 ="(.*?)"/;
147    $self->{ram_dynamic} = (split(",", $1))[0];
148    $html =~ /Query3 ="(.*?)"/;
149    $self->{ram_fix} = (split(",", $1))[0];
150    $self->{ram_used} = $self->{ram_fix} + $self->{ram_dynamic};
151  }
152}
153
154sub check_cpu_subsystem {
155  my ($self) = @_;
156  $self->add_info('checking cpus');
157  $self->add_info(sprintf 'cpu usage is %.2f%%', $self->{cpu_usage});
158  $self->set_thresholds(warning => 40, critical => 60);
159  $self->add_message($self->check_thresholds($self->{cpu_usage}), $self->{info});
160  $self->add_perfdata(
161      label => 'cpu_usage',
162      value => $self->{cpu_usage},
163      uom => '%',
164      warning => $self->{warning},
165      critical => $self->{critical},
166  );
167}
168
169sub check_mem_subsystem {
170  my ($self) = @_;
171  $self->add_info('checking memory');
172  $self->add_info(sprintf 'memory usage is %.2f%%', $self->{ram_used});
173  $self->set_thresholds(warning => 80, critical => 90);
174  $self->add_message($self->check_thresholds($self->{ram_used}), $self->{info});
175  $self->add_perfdata(
176      label => 'memory_usage',
177      value => $self->{ram_used},
178      uom => '%',
179      warning => $self->{warning},
180      critical => $self->{critical},
181  );
182}
183
184
185
186
187
188