[BACK]Return to update_trango.pl CVS log [TXT][DIR] Up to [local] / trango / Net-Telnet-Trango / scripts

Annotation of trango/Net-Telnet-Trango/scripts/update_trango.pl, Revision 1.3

1.1       andrew      1: #!/usr/bin/perl
1.3     ! andrew      2: # $RedRiver: update_trango.pl,v 1.2 2005/11/16 05:26:37 andrew Exp $
1.1       andrew      3: ########################################################################
                      4: # update_trango.pl *** Updates trango foxes with a new firmware
                      5: # 
                      6: # 2005.11.15 #*#*# andrew fresh <andrew@mad-techies.org>
                      7: ########################################################################
                      8: use strict;
                      9: use warnings;
                     10: 
                     11: use Net::Telnet;
1.2       andrew     12: use Net::TFTP;
1.3     ! andrew     13: #use YAML;
1.2       andrew     14: 
                     15: 
1.3     ! andrew     16: my $config_file = shift || 'fox53.conf';
        !            17: my $conf = read_conf($config_file);
1.2       andrew     18: 
1.3     ! andrew     19: my $max_tries = 1;
1.2       andrew     20: 
                     21: 
                     22: 
                     23: 
                     24: 
                     25: 
1.3     ! andrew     26: foreach my $fox (@{ $conf->{'ips'} }) {
        !            27:   print STDERR "Updating: $fox\n";
1.2       andrew     28: 
                     29:   ## Connect and login.
                     30:   my $host = new Net::Telnet (Timeout => 5,
                     31:                               Prompt => '/#> *$/');
1.3     ! andrew     32:   print "Connecting to $fox\n";
1.2       andrew     33:   $host->open($fox);
                     34:   $host->dump_log('dump.log');
                     35: 
                     36:   ## Login to remote host.
                     37:   $host->waitfor(
                     38:     -match => '/password: ?$/i',
                     39:     -errmode => "return",
                     40:   ) or die "problem connecting to host ($fox): ", $host->lastline;
1.3     ! andrew     41: 
        !            42:   my $login_banner = $host->lastline;
        !            43:   my ($type, $version) = $login_banner =~ 
        !            44:     /Welcome to Trango Broadband Wireless (\w+)-(.+)$/i;
        !            45: 
        !            46:   if ($type ne $conf->{'type'}) {
        !            47:     print STDERR "Wrong type of unit ('$type' should be '$conf->{'type'}')\n";
        !            48:     $host->close;
        !            49:     next;
        !            50:   }
        !            51: 
        !            52:   if ($version eq $conf->{'ver'}) {
        !            53:     print STDERR "Already up to date with firmware version '$version'\n";
        !            54:     $host->close;
        !            55:     next;
        !            56:   }
        !            57: 
        !            58:   print "Logging in\n";
        !            59:   $host->print($conf->{'password'});
1.2       andrew     60:   $host->waitfor(
                     61:     -match => $host->prompt,
                     62:     -errmode => "return",
                     63:   ) or die "login ($fox) failed: ", $host->lastline;
                     64: 
1.3     ! andrew     65: 
        !            66:   print "Sending commands\n";
1.2       andrew     67:   ## Send commands
1.3     ! andrew     68:   if ( upload($host, $fox, $conf->{'file_name'}) ) {
        !            69:     print "Rebooting\n";
        !            70:     $host->print("reboot\n");
        !            71:     $host->getline;
1.2       andrew     72:   } else {
1.3     ! andrew     73:     print "Exiting\n";
        !            74:     $host->print("exit\n");
        !            75:     $host->getline;
1.2       andrew     76:   }
                     77:   $host->close;
                     78: }
                     79: 
                     80: sub upload
                     81: {
                     82:   my $host = shift;
1.3     ! andrew     83:   my $fox  = shift;
1.2       andrew     84:   my $file = shift;
1.3     ! andrew     85: 
        !            86:   print "Getting current version\n";
1.2       andrew     87:   my $ver = get_ver($host);
                     88: 
                     89:   if (
1.3     ! andrew     90:     $ver->{'Firmware Version'}  eq $conf->{'ver'} && 
        !            91:     $ver->{'Firmware Checksum'} eq $conf->{'cksum'}
1.2       andrew     92:   ) {
1.3     ! andrew     93:     print STDERR "Already updated!";
1.2       andrew     94:     return 1;
                     95:   }
                     96: 
                     97:   my $try = 0;
                     98:   while (1) {
1.3     ! andrew     99:     if ($try >= $max_tries) {
        !           100:       print STDERR "Couldn't update in $max_tries tries!";
        !           101:       return undef;
        !           102:     }
1.2       andrew    103:     $try++;
                    104: 
1.3     ! andrew    105:     #sysinfo($host);
        !           106:     
        !           107:     print "Enabling TFTPd\n";
1.2       andrew    108:     enable_tftpd($host) || die "Couldn't enable tftpd";
                    109: 
1.3     ! andrew    110:     print "Uploading file\n";
1.2       andrew    111:     # use tftp to push the file up
1.3     ! andrew    112:     my $tftp = Net::TFTP->new($fox, Mode => 'octet');
        !           113: 
        !           114:     $tftp->put($file, $file) 
        !           115:       or die "Error uploading: " . $tftp->error;
1.2       andrew    116: 
                    117:     # waitfor some sort of output
                    118:     # make sure it says 'Success.' otherwise error
1.3     ! andrew    119:     #print "LAST: " . $host->lastline;
        !           120:     #my @lines = $host->getlines;
        !           121:     #print Dump \@lines;
1.2       andrew    122:     
1.3     ! andrew    123:     print "Checking upload\n";
1.2       andrew    124:     my $results = check_tftpd($host);
                    125:     # check the 'File Length' against ???
1.3     ! andrew    126:     if ( $results->{'File Checksum'} ne $conf->{'file_cksum'}) {
        !           127:       print STDERR "File checksum does not match config file!";
        !           128:       next;
        !           129:     }
        !           130: 
        !           131:     if ($results->{'File Length'}   !~ /^$conf->{'file_size'} bytes/) {
        !           132:       print STDERR "File length does not match config file!";
        !           133:       next;
        !           134:     }
1.2       andrew    135: 
1.3     ! andrew    136:     if ( uc($results->{'File Name'}) ne uc($conf->{'file_name'}) ) {
        !           137:       print STDERR "File name does not match config file!";
        !           138:       next;
        !           139:     }
1.2       andrew    140: 
1.3     ! andrew    141:     print "Updating flash\n";
        !           142:     $results = updateflash(
        !           143:       $host, $ver->{'Firmware Checksum'}, $conf->{'cksum'}
        !           144:     ) or die "Couldn't update flash: " . $host->lastline;
        !           145:     unless (
        !           146:       defined $results->{'Checksum'} && 
        !           147:       $results->{'Checksum'} eq $conf->{'cksum'}
        !           148:     ) {
        !           149:       print STDERR "Saved checksum does not match config file!";
        !           150:       next;
1.2       andrew    151:     }
1.3     ! andrew    152:     
        !           153:     print STDERR "Successfully updated!\n";
        !           154:     return 1;
1.2       andrew    155:   }
                    156: }
                    157: 
                    158: sub get_ver
                    159: {
                    160:   my $host = shift;
                    161:   return cmd($host, 'ver');
                    162: }
                    163: 
                    164: sub enable_tftpd
                    165: {
                    166:   my $host = shift;
                    167: 
1.3     ! andrew    168:   my $vals = cmd($host, 'tftpd on', 'Success.');
1.2       andrew    169: 
                    170:   if ($vals->{'Tftpd'} eq 'listen') {
1.3     ! andrew    171:     return $vals;
1.2       andrew    172:   } else {
                    173:     return undef;
                    174:   }
                    175: }
                    176: 
                    177: sub check_tftpd
                    178: {
                    179:   my $host = shift;
1.3     ! andrew    180:   return cmd($host, 'tftpd', 'Success.');
        !           181: }
        !           182: 
        !           183: sub sysinfo
        !           184: {
        !           185:   my $host = shift;
        !           186:   return cmd($host, 'sysinfo', 'Success.');
        !           187: }
        !           188: 
        !           189: sub updateflash
        !           190: {
        !           191:   my $host = shift;
        !           192:   my $old = shift;
        !           193:   my $new = shift;
        !           194: 
        !           195:   return undef unless $new;
        !           196: 
        !           197:   return cmd($host, "updateflash mainimage $old $new", 'Success.', 90);
1.2       andrew    198: }
                    199: 
                    200: sub cmd
                    201: {
                    202:   my $host   = shift;
                    203:   my $string = shift;
1.3     ! andrew    204:   my $expect_last = shift;
        !           205:   my $timeout = shift || 5;
1.2       andrew    206: 
1.3     ! andrew    207:   my @lines = $host->cmd(String => $string, Timeout => $timeout);
1.2       andrew    208: 
                    209:   my $vals = decode_lines(@lines);
1.3     ! andrew    210: 
        !           211:   my $last = $host->lastline;
        !           212: 
        !           213:   unless ($expect_last) {
        !           214:     return $vals;
        !           215:   }
        !           216: 
        !           217:   if ($last =~ /$expect_last$/) {
        !           218:     return $vals;
        !           219:   } else {
        !           220:     warn "Error with command ($string): $last";
        !           221:     return undef;
        !           222:   }
1.2       andrew    223: }
                    224: 
                    225: sub decode_lines
                    226: {
                    227:   my @lines = @_;
                    228: 
                    229:   my %conf;
                    230: 
                    231:   my $key = '';
                    232:   my $val = '';
                    233:   my $in_key = 0;
                    234:   my $in_val = 0;
                    235: 
                    236:   foreach my $line (@lines) {
                    237:     my @chars = split //, $line;
                    238: 
1.3     ! andrew    239:     my $last_key = '';
1.2       andrew    240:     foreach my $c (@chars) {
                    241: 
1.3     ! andrew    242:       if ($c eq '[' || $c eq "\r" || $c eq "\n") {
        !           243:         if ($c eq '[') {
        !           244:           $in_key = 1;
        !           245:           $in_val = 0;
        !           246:         } else {
        !           247:           $in_key = 0;
        !           248:           $in_val = 0;
        !           249:         }
        !           250: 
1.2       andrew    251:         if ($key) {
1.3     ! andrew    252:           $key =~ s/^\s+//;
        !           253:           $key =~ s/\s+$//;
        !           254: 
        !           255:           $val =~ s/^\s+//;
1.2       andrew    256:           $val =~ s/\s+$//;
1.3     ! andrew    257: 
        !           258:           if ($key eq 'Checksum' && $last_key) {
        !           259:             # Special case for these bastids.
        !           260:             my $new = $last_key;
        !           261:             $new =~ s/\s+\S+$//;
        !           262:             $key = $new . " " . $key;
        !           263:           }
        !           264: 
        !           265:           $last_key = $key;
1.2       andrew    266:           $conf{$key} = $val;
                    267:           $key = '';
                    268:           $val = '';
                    269:         }
                    270: 
                    271:       } elsif ($c eq ']') {
                    272:         $in_val = 1;
                    273:         $in_key = 0;
                    274:         $c = shift @chars;
                    275: 
                    276:       } elsif ($in_key) {
                    277:         $key .= $c;
                    278: 
                    279:       } elsif ($in_val) {
                    280:         $val .= $c;
                    281:       }
                    282:     }
                    283:   }
1.3     ! andrew    284:   #print Dump \%conf;
1.2       andrew    285: 
                    286:   if (%conf) {
                    287:     return \%conf;
                    288:   } else {
                    289:     return \@lines;
                    290:   }
                    291: }
1.1       andrew    292: 
1.3     ! andrew    293: sub read_conf
        !           294: {
        !           295:   my $file = shift;
        !           296:   my %conf;
        !           297:   my $in_ip_list = 0;
        !           298:   open my $fh, $file or die "Couldn't open file $file: $!";
        !           299:   while (<$fh>) {
        !           300:     chomp;
        !           301:     next if /^#/;
        !           302:     next if /^$/;
        !           303:     if ($in_ip_list) {
        !           304:       push @{ $conf{'ips'} }, $_;
        !           305:     } else {
        !           306:       my ($key, $val) = split /\s+/, $_, 2;
        !           307: 
        !           308:       if (lc($key) eq 'ips') {
        !           309:         $in_ip_list = 1;
        !           310:         next;
        !           311:       }
        !           312: 
        !           313:       $conf{ lc($key) } = $val;
        !           314:     }
        !           315:   }
        !           316:   close $fh;
        !           317: 
        !           318:   #print Dump \%conf;
        !           319:   foreach (
        !           320:     'password', 
        !           321:     'file_name', 'file_size', 'file_cksum', 
        !           322:     'ver', 'cksum', 'ips',
        !           323:   ) {
        !           324:     die "No $_ specified in config file!"
        !           325:       if (not exists $conf{$_});
        !           326:   }
        !           327: 
        !           328:   return \%conf;
        !           329: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>