#!/usr/bin/perl

use strict;
use warnings;

use Net::Telnet;

my $hostname = shift @ARGV;
my $password = shift @ARGV;

foreach my $attempt (1 .. 3)
{
    eval { query_router($hostname, $password); };
    last unless $@;
}

exit 0;

sub query_router
{
    my $hostname = shift;
    my $password = shift;
    my $t = Net::Telnet->new(Host => $hostname, Errmode => "die");

    $t->waitfor("/Password:/");
    $t->print($password);

    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl chandata\n");
    my $mode = "interleaved";
    my $downbits = get_value($t, "/near-end interleaved channel bit rate: ([0-9]+) kbps/");
    if ($downbits == 0)
    {
        $downbits = get_value($t, "/near-end fast channel bit rate: ([0-9]+) kbps/");
        $mode = "fast";
    }
    my $upbits = get_value($t, "/far-end $mode channel bit rate: ([0-9]+) kbps/");
    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl perfdata\n");
    my $downfec = get_value($t, "/near-end FEC error $mode: *([0-9]+)/");
    my $downcrc = get_value($t, "/near-end CRC error $mode: *([0-9]+)/");
    my $downhec = get_value($t, "/near-end HEC error $mode: *([0-9]+)/");
    my $upfec = get_value($t, "/far-end FEC error $mode: *([0-9]+)/");
    my $upcrc = get_value($t, "/far-end CRC error $mode: *([0-9]+)/");
    my $uphec = get_value($t, "/far-end HEC error $mode: *([0-9]+)/");
    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl linedata near\n");
    my $downmargin = get_value($t, "/noise margin downstream: ([0-9]+\.[0-9]+) db/");
    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl linedata far\n");
    my $upmargin = get_value($t, "/noise margin upstream: ([0-9]+\.[0-9]+) db/");
    $t->waitfor("/^[^>]+>/");
    $t->print("exit\n");

    while ($t->getline) {};

    $t->close();

    print "downstream_bit_rate:$downbits ";
    print "downstream_noise_margin:$downmargin ";
    print "downstream_fec_errors:$downfec ";
    print "downstream_crc_errors:$downcrc ";
    print "downstream_hec_errors:$downhec ";
    print "upstream_bit_rate:$upbits ";
    print "upstream_noise_margin:$upmargin ";
    print "upstream_fec_errors:$upfec ";
    print "upstream_crc_errors:$upcrc ";
    print "upstream_hec_errors:$uphec ";
    print "mode:$mode\n";

    return;
}

sub get_value
{
    my $t = shift;
    my $match = shift;

    my(undef,$data) = $t->waitfor($match);

    return eval "'$data' =~ $match; \$1;";
}
