package Net::Telnet::Trango; use base 'Net::Telnet'; my %PRIVATE = ( is_connected => 0, logged_in => 0, ); sub AUTOLOAD { my $self = shift; my ($method) = (our $AUTOLOAD) =~ /^.*::(\w+)$/ or die "Weird: $AUTOLOAD"; my $success = 'Success.'; my %MEMBERS = ( ver => {}, sysinfo => { waitfor => $success }, tftpd => { waitfor => $success }, ); my %ACCESS = map { $_ => 1 } qw( firmware_version host_type Host is_connected logged_in Timeout ); if (exists $MEMBERS{$method}) { return $self->cmd($method, $MEMBERS{$method}{waitfor}); } if (exists $ACCESS{$method}) { my $var = shift || $PRIVATE{$method}; $PRIVATE{$method} = $var; return $var; } $method = "SUPER::$method"; return $self->$method(@_); } sub new { my $class = shift; my $args = shift || {}; $args->{'Timeout'} ||= 5; $args->{'Prompt'} ||= '/#> *$/'; foreach my $key (keys %{ $args }) { $PRIVATE{$key} = $args->{$key}; } my $self = $class->SUPER::new(%{ $args }); bless $self; #bless $self, $package; return $self; } sub connect { my $self = shift; unless ( $self->open( Host => $self->Host, Errmode => 'return', ) ) { $! = "Couldn't connect to $self->Host. Connection timed out."; return undef, undef; } #$self->dump_log('dump.log'); ## Login to remote host. unless ($self->waitfor( -match => '/password: ?$/i', -errmode => "return", ) ) { $! = "problem connecting to host ($self->Host): " . $self->lastline; return undef; } $self->login_banner($self->lastline); $self->is_connected(1); return ($self->host_type, $self->firmware_version); } sub login { my $self = shift; my $password = shift; $self->print($password); unless ($self->waitfor( -match => $self->prompt, -errmode => "return", ) ) { $! = "login ($self->Host) failed: " . $self->lastline; return undef; } $self->logged_in(1); return $self->logged_in; } sub login_banner { my $self = shift; my $banner = shift || $self->login_banner; my ($type, $ver) = $banner =~ /Welcome to Trango Broadband Wireless (\S+)[\s-]+(.+)$/i; $self->host_type($type); $self->firmware_version($ver); return $banner; } sub reboot { my $self = shift; $self->print("reboot\n"); $self->getline; return 1; } sub exit { my $self = shift; $self->print("exit\n"); $self->getline; return 1; } sub enable_tftpd { my $self = shift; my $vals = $self->cmd('tftpd on', 'Success.'); if ($vals->{'Tftpd'} eq 'listen') { return $vals; } else { return undef; } } sub updateflash { my $self = shift; my $old = shift; my $new = shift; return undef unless $new; return $self->cmd("updateflash mainimage $old $new", 'Success.', 90); } sub cmd { my $self = shift; my $string = shift; my $expect_last = shift; my $timeout = shift || $self->Timeout; unless (defined $string) { $! = "No command passed"; return undef; } unless ($self->is_connected) { $! = "Not connected"; return undef; } unless ($self->logged_in) { $! = "Not logged in"; return undef; } my @lines = $self->SUPER::cmd(String => $string, Timeout => $timeout); my $vals = _decode_lines(@lines); unless ($expect_last) { return $vals; } my $last = $self->lastline; if ($last =~ /$expect_last$/) { return $vals; } else { warn "Error with command ($string): $last"; return undef; } } sub _decode_lines { my @lines = @_; my %conf; my $key = ''; my $val = ''; my $in_key = 0; my $in_val = 0; foreach my $line (@lines) { my @chars = split //, $line; my $last_key = ''; foreach my $c (@chars) { if ($c eq '[' || $c eq "\r" || $c eq "\n") { if ($c eq '[') { $in_key = 1; $in_val = 0; } else { $in_key = 0; $in_val = 0; } if ($key) { $key =~ s/^\s+//; $key =~ s/\s+$//; $val =~ s/^\s+//; $val =~ s/\s+$//; if ($key eq 'Checksum' && $last_key) { # Special case for these bastids. my $new = $last_key; $new =~ s/\s+\S+$//; $key = $new . " " . $key; } $last_key = $key; $conf{$key} = $val; $key = ''; $val = ''; } } elsif ($c eq ']') { $in_val = 1; $in_key = 0; $c = shift @chars; } elsif ($in_key) { $key .= $c; } elsif ($in_val) { $val .= $c; } } } #print Dump \%conf; if (%conf) { return \%conf; } else { return \@lines; } }