sout11 has asked for the wisdom of the Perl Monks concerning the following question:

Hello there. I have been trying to logon to switches using an array to collect switch IPs and then log onto the switches. I got 2 different ways that I have to use to log on to the switches depending on the configuration of the switches. Some of the switches require a username and password and some only require a password, here is my code for both ways:

#login 1 foreach $host ( @hosts ) { my $conn = Net::Telnet::Cisco::IOS->new( +HOST => $host); # connect to the host $conn->login( Name => $username, Password => $password); $conn->close; }; #Login 2 foreach $host ( @hosts ) { my $conn = Net::Telnet::Cisco::IOS->new( +HOST => $host); # connect to the host $conn->login( Passcode => $passw); $conn->close; };

Both these login ways is tested and works on switches with the different configs. What I want to do is to have both of these in one script so that I can run through the whole range of switches. I was thinking of using an IF statement, but being a noob I dont really know where to start. This is what I was thinking about doing:

foreach $host ( @hosts ) { my $conn = Net::Telnet::Cisco::IOS->new +(HOST => $host); # connect to the host if ( $conn->login( Name => $username, Password => $password)); else( $conn->login( Passcode => $passw));

I know my coding layout is wrong and I am not looking to be spoon fead, but would like someone to point me in the right direction. Thanks

Replies are listed 'Best First'.
Re: Net telnet Cisco Login
by moritz (Cardinal) on Aug 25, 2009 at 12:29 UTC
    I don't see off-hand what's wrong about it. Have you tried it? What result did you get?

    Maybe the routers don't allow multiple login attempts per session. If that's the case you either have to open a new connection for the second login attempt, or store for each router if it needs a username, and only use the desired authentication method.

    Perl 6 projects - links to (nearly) everything that is Perl 6.

      Thanks for the reply moritz, The problem I having is due to compilation errors within my IF statement, I will have to tell it when it is equal to something then login in using method 1 else use method 2:

      if (login=???){$conn->login( Name => $username, Password => $password); } else {$conn->login( Passcode => $passw); };

      I am hitting a brick wall with this if statement, Thanks again for the quick reply

Re: Net telnet Cisco Login
by ssandv (Hermit) on Aug 25, 2009 at 15:44 UTC
    In a similar situation, we found that the best way was to use ->waitfor(match), using a regex that matched whichever prompt came up first, and then do a conditional based on the match result, rather than using ->login. Net::Telnet's login isn't really designed to cope with this situation, but you can do almost anything with a clever use of waitfor.

      Thanks ssandv, looks like I am getting somewhere and my code is not giving any comp errors. I have tried the  ->waitfor (match) and it seems to be working in a way. Here is my new code:

      foreach $host ( @hosts ) { my $conn = Net::Telnet::Cisco->new(HOST => $host, Dump_log => + 'dump2.log',Timeout=>20, ErrMode => 'return'); if ($conn -> waitfor ('/Password:.*/')){ $conn->login( Passcode => $passw); } else { $conn->login( Name => $username, Password => $password) or die "ERROOOOR"; } print $conn->cmd("show int status"); $conn->close; };

      The problem I am having now I know is with my regex statement. I am getting no output from my script, but when I replace $conn -> waitfor ('/Password:.*/') with $conn -> waitfor ('/Username:.*/') it will give what I request from switches where I only need to give the password. This is what my dump file gives:

      < 0x00000: ff fb 01 ff fb 03 ff fd 18 ff fd 1f 0d 0a 0d 0a ÿû.ÿû.ÿ +ý.ÿý..... < 0x00010: 55 73 65 72 20 41 63 63 65 73 73 20 56 65 72 69 User Ac +cess Veri < 0x00020: 66 69 63 61 74 69 6f 6e 0d 0a 0d 0a 50 61 73 73 ficatio +n....Pass < 0x00030: 77 6f 72 64 3a 20 word: > 0x00000: ff fd 01 ff fd 03 ff fc 18 ff fc 1f ÿý.ÿý.ÿ +ü.ÿü. < 0x00000: ff fe 18 ff fe 1f ÿþ.ÿþ. > 0x00000: 73 68 6f 77 20 69 6e 74 20 73 74 61 74 75 73 0d show in +t status. > 0x00010: 0a . < 0x00000: 0d 0a 50 61 73 73 77 6f 72 64 3a 20 ..Passw +ord:

      Please have a look at my regex statement. Any quidance will be welcome. Thanks

      Thanks

        Well, first I think you shouldn't be using login with waitfor. You'll use print because waitfor captured the prompt and I don't think login will see it after that.

        Second, you missed the whole point of using a regex there. If you read the Net::Telnet documentation on waitfor, you'll see that

        my ($prematch, $match)= $obj->waitfor($matchop);
        gives you the string that matched in $match. So, if you use a regex like /(Password|Username)/ and a list assignment (again, I got this straight from the documentation for the module), then $match tells you whether you need to $obj->print a password or username string. Naturally if you print a username, you should then waitfor the password prompt and print the password. login attempts to simplify this stuff, but it's extremely picky about what it expects to see.

        Your code needs to do the job of login, not try to work alongside it. A direct quote from the login section of Net::Telnet: "Consider using a combination of print() and waitfor() as an alternative to this method when it doesn't do what you want, e.g. the remote host doesn't prompt for a username."