http://www.perlmonks.org?node_id=24556


in reply to (Ozymandias: Post it!) RE:(2) Checking ADSL connection
in thread Checking ADSL connection

Here is my code... It is VERY tuned to my particular situation and doesn't have many (any?) comments...

Ozymandias, I haven't looked at your code recently, but one of the things emphasized in mine is a strong logging capability (via syslog).

One thing I'd like to add is "upstream failure detection" where it will not restart the connection if the modem and the next router "upstream to the internet" both respond to pings. Also I'd like to add code to do error-checking of the results of the "/etc/rc.d/init.d/pppoe start" command.

#!/usr/bin/perl -w use strict; use Device::SerialPort; use ControlX10::CM11; use Net::Ping; use Net::Syslog; use POSIX; # DAEMON stuff my $pid=fork; exit if $pid; die "Couldn't fork: $!" unless defined $pid; POSIX::setsid() or die "Can't start a new session: $!"; # end DAEMON stuff my $s=new Net::Syslog(Facility=>'local5', Priority=>'notice', Name=>'dslmonitor'); $SIG{TERM}=sub { $s->send('DSL monitoring stopping'); exit; }; $s->send('DSL monitoring started'); my $i; my $m; my $ctr=0; my $tdown; while(1){ $m=is_modem_up(); if(!$m){ $s->send("modem not responding to ping"); } $i=is_internet_up() if(($ctr==0)||(!$m)); if((!$i)||(!$m)){ $s->send('lost internet connection'); $tdown=time(); } while((!$i)||(!$m)){ $s->send('stopping pppoe'); stop_pppoe(); $m=0; while(!$m){ $s->send('power cycling DSL modem'); power_cycle_modem(); $s->send('power cycling complete, waiting for modem to respond t +o ping'); my $b=time; my $tdiff=time()-$b; while(($tdiff<30)&&(!$m)){ sleep 1; $m=is_modem_up(); $tdiff=time()-$b; } if($m){ $s->send("modem up $tdiff sec after cycle\n"); }else{ $s->send("modem not responding to pings $tdiff seconds after r +eboot, power cycle modem again"); } } $s->send("waiting 30 seconds for modem DSL negotiation to occur"); sleep 30; $s->send("starting pppoe"); start_pppoe(); $s->send("pppoe start complete, waiting 5 seconds"); sleep 5; $s->send("probing for connectivity"); $i=is_internet_up(); $m=is_modem_up(); if(!$m){ $s->send("modem not responding to ping"); } if(($i)&&($m)){ $tdown=time()-$tdown; my $se=$tdown%60; my $m=(int($tdown/(60)))%60; my $h=(int($tdown/(60*60)))%24; my $d=(int($tdown/(60*60*24))); $s->send("internet connection restored after $d days, $h hours, +$m minutes and $se seconds of downtime"); }else{ $s->send("pppoe negotiation failed"); } } sleep 30; $ctr=($ctr+1)%10; } sub is_modem_up{ my $p=new Net::Ping("icmp"); for(my $c=0;$c<3;$c++){ my $i=$p->ping('10.0.0.1',2);; return $i if($i); } return 0; } sub is_internet_up{ my $p=new Net::Ping("icmp"); my @inethosts=('192.5.5.241','202.12.27.33','128.63.2.53'); for(my $c=0;$c<3;$c++){ foreach(@inethosts){ my $i= $p->ping($_,5); return $i if($i); } } $s->send("internet not responding to ping"); return 0; } sub stop_pppoe{ system '/etc/rc.d/init.d/adsl stop >/dev/null 2>/dev/null'; } sub start_pppoe{ system '/etc/rc.d/init.d/adsl start >/dev/null 2>/dev/null'; # checking output would be a good idea } sub power_cycle_modem{ #my $serial_port = new Device::SerialPort('/dev/x10'); my $serial_port = new Device::SerialPort('/dev/ttyS0'); if(!defined $serial_port){ die "error openign serial \"$!\""; } $serial_port->baudrate(4800); $serial_port->databits(8); $serial_port->parity('none'); $serial_port->stopbits(1); $serial_port->handshake('none'); $serial_port->stty_echo(0); $serial_port->read_const_time(5000); $serial_port->read_char_time(5); &ControlX10::CM11::send($serial_port, 'B1'); &ControlX10::CM11::send($serial_port, 'BK'); sleep 5; &ControlX10::CM11::send($serial_port, 'B1'); &ControlX10::CM11::send($serial_port, 'BJ'); }