Home AMX User Forum NetLinx Studio

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!
.

Comments

  • truetrue Posts: 307
    That's a telnet negotiation sequence. Completely expected for a telnet daemon.

    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?
  • chillchill Posts: 186
    true wrote: »
    That's a telnet negotiation sequence. Completely expected for a telnet daemon.

    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.
    .
  • AMXJeffAMXJeff Posts: 450
    chill wrote: »
    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 = "";
    				}
    			}
    		}
    
  • chill wrote: »
    The specific string I get back is "$FF$FD%$FF$FB$01$FF$FB$03$FF$FD'$FF$FD$1F$FF$FD.

    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.
  • chillchill Posts: 186
    Thanks to all for the quick and useful replies. Regarding RFC854, it seems that a pretty definitive link would be http://www.ietf.org/rfc/rfc854.txt; page 14 is the money shot. What google found for me is http://developer.tandberg.com/web/guest/forum/-/message_boards/message/21536 - useful, but not as useful as it first seemed.

    Thanks again!
    .
  • HedbergHedberg Posts: 671
    We had a discussion about XP Professional telnet clients and how the Netlinx IP Client fails to properly negotiate the Telnet configuration back in 2007. In order to get it to work, I used ethereal (now Wireshark) to watch a client that would properly connect to the XP server and then coded up the Netlinx IP client to mimic that. A guy who used to post here named Bob did some more work with the Netlinx client and one or more telnet servers. Look at this thread:http://www.amxforums.com/showthread.php?2702-IP_CLIENT_OPEN-to-ssh-port-22&highlight= to see what the problems and solutions were.
  • viningvining Posts: 4,368
    Here's some code I wrote for a telnet session with Cisco switches last year. Might be useful.
    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 Size
    
    and 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.///////////////////////
    
  • truetrue Posts: 307
    Others got to it before me - the reason your TELNET clients worked with the TELNET server is because they are TELNET clients. The reason raw connections like via NetLinx ip_client_open give you the sequence to a TELNET server is because it is a TELNET server. Other stuff works with both client types because other stuff isn't a TELNET server - it is a raw character connection.

    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.
Sign In or Register to comment.