2

[Python telnetlib read_until recv problem]

"read_until" function returns cut off string with long commands.
The commands ran perfectly, but it does not show full texts.
How can I fix this? Please help.

# my code

tn = telnetlib.Telnet(ip, 23, 5)
prompt = ']# '
tn.write('echo "this is a long command for the test purpose... > test.txt"\n')
print tn.read_until(prompt, 1)

# debug output

Telnet(192.168.220.4,23): send 'echo "this is a long command for the test purpose... > test.txt"\n'
Telnet(192.168.220.4,23): recv 'echo "this is a l'
Telnet(192.168.220.4,23): recv 'ong command for the test purpose... > te\r\x00<his is '
Telnet(192.168.220.4,23): recv 'a long command for the test purpose... > tes '
Telnet(192.168.220.4,23): recv ' \x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x0 8t.txt"'
Telnet(192.168.220.4,23): recv '\r\nthis is a long command for the test purpose... >'
Telnet(192.168.220.4,23): recv ' test.txt\r\n[root@RHEL6-5 tmp]# '

# real output

<his is a long command for the test purpose... > test.txt"
this is a long command for the test purpose... > test.txt
[root@RHEL6-5 tmp]#

Community
  • 1
  • 1
curtis
  • 23
  • 1
  • 5
  • Seeing the same issue. Looks like a line wrap problem, but can't figure out how to turn this off. – monkut Aug 02 '16 at 04:44

2 Answers2

3

The issue appears to be occurring due to line-wrapping. I found a solution where setting the window size width to near the max value allows long lines to be received without line-wrapping applied by the telnet server.

(See the Window Size Option RFC for details on setting the option https://www.ietf.org/rfc/rfc1073.txt )

import telnetlib
import struct
from telnetlib import DO, DONT, IAC, WILL, WONT, NAWS, SB, SE

MAX_WINDOW_WIDTH = 65000  # Max Value: 65535
MAX_WINDOW_HEIGHT = 5000


def set_max_window_size(tsocket, command, option):
    """
    Set Window size to resolve line width issue
    Set Windows size command: IAC SB NAWS <16-bit value> <16-bit value> IAC SE
    --> inform the Telnet server of the window width and height.
    Refer to https://www.ietf.org/rfc/rfc1073.txt
    :param tsocket: telnet socket object
    :param command: telnet Command
    :param option: telnet option
    :return: None
    """
    if option == NAWS:
        width = struct.pack('H', MAX_WINDOW_WIDTH)
        height = struct.pack('H', MAX_WINDOW_HEIGHT)
        tsocket.send(IAC + WILL + NAWS)
        tsocket.send(IAC + SB + NAWS + width + height + IAC + SE)
    # -- below code taken from telnetlib source
    elif command in (DO, DONT):
        tsocket.send(IAC + WONT + option)
    elif command in (WILL, WONT):
        tsocket.send(IAC + DONT + option)

ip = 'x.x.x.x'
tn = telnetlib.Telnet(ip, 23, timeout=5)
tn.set_option_negotiation_callback(set_max_window_size)

tn.write('echo "this is a long command for the test purpose... > test.txt"\n')

prompt = ']# '
print tn.read_until(prompt, timeout=1)
monkut
  • 42,176
  • 24
  • 124
  • 155
  • That will only resolve your issue by chance and you might still encounter the problem occasionally, even with that "fix". The real problem here is a misunderstanding of the `read_until()` function. `read_until()` doesn't block, which means it operates only on the data that already entered the host, which may be cut off at any arbitrary point due to how TCP works. What you really want to use is the `expect()` function. – blubberdiblub Jan 12 '17 at 22:06
  • To: blubberdiblub Thank you!!! expect() function works great. I don't lose any strings!!! Until now I thought read_until() function does blocking... – curtis Mar 01 '17 at 08:25
  • Thank you so much! Just pointing out, for the unsigned short (`H`) which you used, you're right that the maximum is 65536, but I think you actually need `!H`, to get the endianness right for the network! – ackerleytng Sep 24 '17 at 02:37
0

Working for me.

def set_max_window_size(tsocket, command, option):
"""
Set Window size to resolve line width issue
Set Windows size command: IAC SB NAWS <16-bit value> <16-bit value> IAC SE
--> inform the Telnet server of the window width and height.
Refer to https://www.ietf.org/rfc/rfc1073.txt
:param tsocket: telnet socket object
:param command: telnet Command
:param option: telnet option
:return: None
"""
if option == NAWS:
    naws_command = struct.pack('!BBBHHBB',
    255, 250, 31, # IAC SB NAWS
    50, 100, #width, height
    255, 240) # IAC SE
    tsocket.send(naws_command)
# -- below code taken from telnetlib source
elif command in (DO, DONT):
    tsocket.send(IAC + WONT + option)
elif command in (WILL, WONT):
    tsocket.send(IAC + DONT + option)

ip = 'x.x.x.x'
tn = telnetlib.Telnet(ip, 23, timeout=5)
socket = tn.get_socket()
tn.set_option_negotiation_callback(set_max_window_size)

tn.write('echo "this is a long command for the test purpose... > test.txt"\n')

prompt = ']# '
print tn.read_until(prompt, timeout=1)
  • Could you please add some additional information why your code solves the problem? – slfan May 07 '19 at 09:24
  • shure. print(IAC + SB + NAWS + width + height + IAC + SE) b'\xff\xfa\x1f2\x00d\x00\xff\xf0' print(naws_command) b'\xff\xfa\x1f\x002\x00d\xff\xf0' During concatenation in the example above, the bytes were shifted and the command was not correct. – Богдан Соловьев May 07 '19 at 11:37