#!/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("/Enter.*Menu.*Selection.*Number:/");
    $t->print("24");
    $t->waitfor("/Enter.*Menu.*Selection.*Number:/");
    $t->print("8");

    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl chandata\n");
    my $standard = get_value($t, "/DSL standard: (.*)/");
    my $mode;
    my $downbits;
    my $upbits;	
    if ($standard eq "ADSL_G.dmt")
    {
        $downbits = get_value($t, "/near-end interleaved channel bit rate: ([0-9]+) kbps/");

        if ($downbits > 0)
        {
            $mode = "interleaved"
        }
        else
        {
            $downbits = get_value($t, "/near-end fast channel bit rate: ([0-9]+) kbps/");
            $mode = "fast";
        }

        $upbits = get_value($t, "/far-end $mode channel bit rate: ([0-9]+) kbps/");
    }
    elsif ($standard eq "ADSL2+ Mode")
    {
        $mode = "fast";
        $downbits = get_value($t, "/near-end bit rate: ([0-9]+) kbps/");
        $upbits = get_value($t, "/far-end bit rate: ([0-9]+) kbps/");
    }
    else
    {
        die "Unknown standard: $standard";
    }
    $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]+) db/");
    $t->waitfor("/^[^>]+>/");
    $t->print("wan adsl linedata far\n");
    my $upmargin = get_value($t, "/noise margin upstream: ([0-9]+) db/");
    $t->waitfor("/^[^>]+>/");
    $t->print("exit\n");
    $t->waitfor("/Enter.*Menu.*Selection.*Number:/");
    $t->print("99");

    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 0;
}

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

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

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