cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2356
Views
0
Helpful
6
Replies

TCL Socket Help

Marc D
Level 1
Level 1

I've been trying to write a script that would telnet to another device to run some commands. Unfortunately, whatever I do, it seems I'm never getting past the motd banner. When executed, the script does open the session, and I get the full banner, but then it stops until the other device times out. I never the "Username:" prompt. Wireshark tells me the prompt is delivered, so I don't know what I'm doing wrong.

Help!

proc waitfor {sock pattern {delay 500}} {
  while { 1 } {
    after $delay { return -code error "delay expired" }
    gets $sock line
    puts $line
    if { [string match [string tolower $pattern] [string tolower $line]] } {
      puts "match"
      return -code ok
    }
  }
}

set host "yoink!"
set username "yoink!"
set password "yoink!"
set hostname "yoink!"

puts "Trying to connect to $host\n\n"
set sock [socket $host 23]

waitfor $sock "username:"
puts $sock $username
waitfor $sock "password:"
puts $sock $password
waitfor $sock "$hostname#"
puts $sock "show clock"
waitfor $sock "$hostname#"

close $sock

6 Replies 6

Marc D
Level 1
Level 1

After some more tests, I found something odd.

Here's an output while running the script.

router#tclsh tftp://10.120.1.2/telnet3.tcl
Loading telnet3.tcl from 10.120.1.2 (via GigabitEthernet0/0): !
[OK - 811 bytes]
Trying to connect to 10.180.39.1


{^A{^C}^X}^_    <- Telnet negociation garbage

MOTD Banner Here!

Username:       <- There's a long delay (auth timeout) before this appears
                   And all following lines appear at once.  
step 2          <- Some debug
% Username:  timeout expired!
error reading "sock0": broken pipe
    while executing
"gets $sock line"
    (procedure "waitfor" line 4)
    invoked from within
"waitfor $sock "password:""
    (file "tftp://10.120.1.2/telnet3.tcl" line 28)

router#

      

So I did a manual telnet, and it looks like this.

router#telnet 10.180.39.1
Trying 10.180.39.1 ... Open


MOTD Banner Here!


User Access Verification  <- This line doesn't appear in the script

Username:

So it seems this line is causing the script to bog down somehow.

Waiting doesn't help when it comes to sockets.  You need to read from them to drain them of data.  Have a look at

http://wiki.tcl.tk/684 for an example Tcl telnet client.  This client will also handle the telnet negotiation characters for you.

If I take this down to its simplest form, it looks something like this:

set sock [socket 10.10.128.201 23]

while {[gets $sock line] >= 0 } {
  puts $line
}

close $sock

Technically, if I run this, it should give me the same output as if I telnet from the originating device. When I do telnet, I get this:

switch#telnet 10.10.128.201
Trying 10.10.128.201 ... Open


User Access Verification

Password:

When I run the script, I get this:

switch#tclsh tftp://10.120.1.2/telnet5.tcl

Loading telnet5.tcl from 10.120.1.2 (via Vlan31): !
[OK - 129 bytes]
{^C{^A{^C{^A

User Access Verification

I still don't get that final line, and I don't know why.

Because you aren't speaking the telnet protocol.  Telnet is more than a raw socket.  Those negotiation options control things like echo and flow control.  You need to acknowledge them in order to continue the session.

I think I figured out at least part of the problem. The username, password or router prompts don't end with a CrLf. From what I'm reading, they can't be pulled with a gets as long as it hasn't reached an eol. I've tried using the previous line's text as my trigger to send the proper input and now I'm getting further.

Do you know how I can make gets / fconfigure ignore oel's and send whatever it has? I'd have to reconstruct lines myself, but I don't think I have much of a choice.

As an aside, in a previous iteration, I parsed and answered the WILLs and DOs with WONTs and DOs, and the telnet server (from a debug telnet on the receiving device) liked them, but it didn't change the behavior regarding the last line. I think the CrLf makes sence.

Thank you for your precious help.

I was able to make the telnet client example I posted work (I got the prompts).  There were two things I needed to change, though.  One was to change iso8859-1 to utf-8 and the other was to change the "$byte" variable in the switch statement of the protocol function to "$op".  Then you can add in your bits to automatically interact with the prompts.  The other fconfigures in there already do the job for making the socket fully readable.

Another option you might consider, which might be a bit easier, is to wrap the "telnet" CLI command from IOS.  If you interact with that, it takes all of the socket reading and writing out of the equation.  I did a script called the EASy command shell at http://www.cisco.com/go/easy that does this.

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: