Telnet into a Windows XP box
I have a piece of gear to control via telnet. It's a Vista X20 Spyder, but it's really Windows XP Embedded underneath. I need to be able to telnet into it from my NI-4100. I've set up the Spyder to allow this.
The issue is that when I telnet from Netlinx, it sends a string of hex gibberish. The specific string I get back is "$FF$FD%$FF$FB$01$FF$FB$03$FF$FD'$FF$FD$1F$FF$FD. I get the expected behavior (prompt for username and password) from three different telnet clients on my laptop, and I've gotten the bad behavior on two different Windows 'server' boxes when connecting from Netlinx. AMX tech support was able to reproduce the bad behavior, even to the point of getting that same string of hex back from the server on connection. They've put in an RFI, but we know where that will lead.
Any ideas?
Thanks!
.
The issue is that when I telnet from Netlinx, it sends a string of hex gibberish. The specific string I get back is "$FF$FD%$FF$FB$01$FF$FB$03$FF$FD'$FF$FD$1F$FF$FD. I get the expected behavior (prompt for username and password) from three different telnet clients on my laptop, and I've gotten the bad behavior on two different Windows 'server' boxes when connecting from Netlinx. AMX tech support was able to reproduce the bad behavior, even to the point of getting that same string of hex back from the server on connection. They've put in an RFI, but we know where that will lead.
Any ideas?
Thanks!
.
0
Comments
Telnet isn't what most use it as - that being a raw client. Telnet does have some commands but a telnet client is supposed to understand them.
What client(s) are you using to connect?
Without problems: TeraTerm, Hyperterm, Windows telnet from the prompt. With problems: Netlinx ip_client_open, which has worked for me for many years for everything else.
I didn't really expect that sequence from the daemon, because such things don't appear when telnetting to, e.g., an Accordent capture station (another Windows-based appliance), or an Extron switch, or a Biamp, or a Polycom codec, all of which I've controlled via IP from Netlinx in the past.
Thanks for the reply, and for the hint; I'll see what Mister Google has to say about this.
.
Search for RFC854... Goes into the Telnet protocol.
This is what I normally do to config a telnet client from a server perspective.
WHILE (FIND_STRING(sIPBuffer, "$FF", 1) > 0) { WHILE (LEFT_STRING(sIPBuffer,1) != "$FF") GET_BUFFER_CHAR(sIPBuffer); IF (LENGTH_STRING(sIPBuffer) < 3) BREAK; cTelnetCmd = GET_BUFFER_STRING(sIPBuffer,3); SELECT { // WILL <=== WE DONT WANT YOU TO DO ANYTHING! ACTIVE (FIND_STRING(cTelnetCmd,"$FF,$FB",1) > 0): { SEND_STRING dvConfigServer,"$FF, $FE, cTelnetCmd[3]" } // DO SUPPRESS GO AHEAD ACTIVE (FIND_STRING(cTelnetCmd,"$FF,$FD,$03",1) > 0): { SEND_STRING dvConfigServer,"$FF, $FB, cTelnetCmd[3]" } // DO ECHO <== WHAT WE REALLY WANT ACTIVE (FIND_STRING(cTelnetCmd,"$FF,$FD,$01",1) > 0): { nStage = 1; sTelnetCommand = ""; } } }This is not a "bad" response. The server is negotiating the telnet options. See http://www.networksorcery.com/enp/protocol/telnet.htm for an explanation of telnet options.
I believe this is saying:
$FF$FD% = IAC DO Authentication
$FF$FB$01 = IAC WILL Echo
$FF$FB$03 = IAC WILL Suppress-go-ahead
$FF$FD' = IAC DO New Environment Option
$FF$FD$1F = IAC DO Negotiate About Window Size
and not sure about the last since you only seem to have $FF$FD.
Thanks again!
.
DEFINE_CONSTANT //TELNET COMMANDS (NOT CISCO COMMANDS BUT SESSION STUFF!) "$FF$FB$01$FF$FB$03$FF$FD$18$FF$FD$1F" CHAR TELNET_IAC[1] = {$FF} CHAR TELNET_NEG_RX[12] = {$FF,$FB,$01,$FF,$FB,$03,$FF,$FD,$18,$FF,$FD,$1F} CHAR TELNET_NEG_RESPONSE[12] = {$FF,$FE,$01,$FF,$FC,$03,$FF,$FC,$18,$FF,$FC,$1F} CHAR TELNET_DONT_ECHO[3] = {$FF,$FE,$01} CHAR TELNET_WONT_ECHO[3] = {$FF,$FC,$01} CHAR TELNET_END_SUBNEG[2] = {$FF,$F0} CHAR TELNET_DO_SUPP_GOAHEAD[3] = {$FF,$FD,$03} CHAR TELNET_WILL_TERMTYPE[3] = {$FF,$FB,$18} CHAR TELNET_WONT_WINDSIZE[3] = {$FF,$FC,$1F} //$FF = IAC (interpret as command) or extended options list //$FE = DON'T //$FD = DO //$FC = WON'T //$FB = WILL //$FA = START SUB NEGOTIATIONS //$F0 = END OF SUB NEGOTIATIONS //$F9 = GO AHEAD SIGNAL //$F3 = NVT BREAK CHARACTER BRK //$F2 = DATA MARK //$F1 = NOP NO OPERATIONS //$1 = ECHO //$3 = SUPPRES GO AHEAD //$18 = TERMINAL TYPE //$1F = NEGOTIATE WINDOW SIZE (* Commands Dec Hex Description ---------------------------------------------------------------- data All terminal input/output data. End subNeg 240 FO End of option subnegotiation command. No Operation 241 F1 No operation command. Data Mark 242 F2 End of urgent data stream. Break 243 F3 Operator pressed the Break key or the Attention key. Int process 244 F4 Interrupt current process. Abort output 245 F5 Cancel output from current process. You there? 246 F6 Request acknowledgment. Erase char 247 F7 Request that operator erase the previous character. Erase line 248 F8 Request that operator erase the previous line. Go ahead! 249 F9 End of input for half-duplex connections. SubNegotiate 250 FA Begin option subnegotiation. Will Use 251 FB Agreement to use the specified option. Won’t Use 252 FC Reject the proposed option. Start use 253 FD Request to start using specified option. Stop Use 254 FE Demand to stop using specified option. IAC 255 FF Interpret as command. *) //Command: Do Echo //Command: Do Suppress Go Ahead //Command: Won't Terminal Type //Command: Won't Negotiate About Window Sizeand the applicable parts in my rx string function:DEFINE_FUNCTION fnDevMod_String(CHAR iData_Txt[]) { SELECT { ACTIVE(sJAP.nAccessLevel == LEVEL_ZERO): { LOCAL_VAR INTEGER nBadPasses ; ////fnDevMod_DeBug("'fnDevMod_String: LZ "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; SELECT { ACTIVE(sJAP.cLstCmd == CLEAR_TO_SEND): { LOCAL_VAR INTEGER nNegotiate ; ////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; SELECT { ACTIVE(find_string(iData_Txt,TELNET_NEG_RX,1)): { REMOVE_STRING(iData_Txt,TELNET_NEG_RX,1) ; nNegotiate = 1 ; } ACTIVE(find_string(iData_Txt,'Password: ',1)): { REMOVE_STRING(iData_Txt,'Password: ',1) ; fnClear_ToSend() ; //before q cmd if(nNegotiate) { nNegotiate = 0 ; fnQueue_QCmd("TELNET_NEG_RESPONSE") ; } else { fnQueue_QCmd(sJAP.cPassword) ; } } ACTIVE(TRUE): { ////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; } } } ACTIVE(sJAP.cLstCmd[1] == TELNET_IAC): { ////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; SELECT { (* ACTIVE(find_string(iData_Txt,"$FF,$FC,$01",1)): { REMOVE_STRING(iData_Txt,"$FF,$FC,$01",1) ; } ACTIVE(find_string(iData_Txt,"$FF,$FE,$18",1)): { REMOVE_STRING(iData_Txt,"$FF,$FE,$18",1) ; } *) ACTIVE(find_string(iData_Txt,"$FF,$FE,$1F",1)): { //REMOVE_STRING(iData_Txt,"$FF,$FE,$1F",1) ; fnClear_ToSend() ; //before q cmd fnQueue_QCmd(sJAP.cPassword) ; } (* ACTIVE(iData_Txt == TELNET_END_SUBNEG): { REMOVE_STRING(iData_Txt,TELNET_END_SUBNEG,1) ; } ACTIVE(find_string(iData_Txt,'User Access Verification',1)): { REMOVE_STRING(iData_Txt,'User Access Verification',1) ; } ACTIVE(find_string(iData_Txt,'% Password: timeout expired!',1)): { REMOVE_STRING(iData_Txt,'% Password: timeout expired!',1) ; } *) ACTIVE(find_string(iData_Txt,'% Bad passwords',1)): { nBadPasses ++ ; //REMOVE_STRING(iData_Txt,'% Bad passwords',1) ; } ACTIVE(find_string(iData_Txt,'Password: ',1)): { //REMOVE_STRING(iData_Txt,'Password: ',1) ; fnClear_ToSend() ; //before q cmd fnQueue_QCmd(sJAP.cPassword) ; } ACTIVE(find_string(iData_Txt,'Switch>',1)): { nBadPasses = 0 ; //REMOVE_STRING(iData_Txt,'Switch>',1) ; sJAP.nAccessLevel = LEVEL_SWITCH_USER ; fnClear_ToSend() ; //before q cmd fnQueue_QCmd('enable') ; } ACTIVE(TRUE): { ////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; } } } ACTIVE(sJAP.cLstCmd == sJAP.cPassword): { ////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; SELECT { (* ACTIVE(find_string(iData_Txt,"$FF,$FC,$01",1)): { REMOVE_STRING(iData_Txt,"$FF,$FC,$01",1) ; } ACTIVE(find_string(iData_Txt,"$FF,$FE,$18",1)): { REMOVE_STRING(iData_Txt,"$FF,$FE,$18",1) ; } ACTIVE(find_string(iData_Txt,"$FF,$FE,$1F",1)): { REMOVE_STRING(iData_Txt,"$FF,$FE,$1F",1) ; } ACTIVE(iData_Txt == TELNET_END_SUBNEG): { REMOVE_STRING(iData_Txt,TELNET_END_SUBNEG,1) ; } ACTIVE(find_string(iData_Txt,'User Access Verification',1)): { REMOVE_STRING(iData_Txt,'User Access Verification',1) ; } ACTIVE(find_string(iData_Txt,'% Password: timeout expired!',1)): { //REMOVE_STRING(iData_Txt,'% Password: timeout expired!',1) ; } *) ACTIVE(find_string(iData_Txt,'% Bad passwords',1)): { nBadPasses ++ ; //REMOVE_STRING(iData_Txt,'% Bad passwords',1) ; } ACTIVE(find_string(iData_Txt,'Switch>',1)): { nBadPasses = 0 ; //REMOVE_STRING(iData_Txt,'Switch>',1) ; sJAP.nAccessLevel = LEVEL_SWITCH_USER ; fnClear_ToSend() ; //before q cmd fnQueue_QCmd('enable') ; } ACTIVE(iData_Txt == 'Password: '): { //REMOVE_STRING(iData_Txt,'Password: ',1) ; fnClear_ToSend() ; //before q cmd if(nBadPasses < 3) { fnQueue_QCmd(sJAP.cPassword) ; } } ACTIVE(TRUE): { //////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; } } } ACTIVE(TRUE): { //////fnDevMod_DeBug("'fnDevMod_String: "',iData_Txt,'" :DEBUG <',ITOA(__LINE__),'>'") ; } } } cont.///////////////////////Hopefully the info others gave you fills you in on what TELNET is and why, while many of us use TELNET clients as raw character clients, a TELNET connection is different from just a raw data / character connection. You are not actually 'telnetting' into your other servers (Biamp, Extron, etc), just using a TELNET client to swap characters and such around as there is no TELNET negotiation.