/* NVT.c -- simple telnet for WIN32-console * * Author * Hirofumi Fujii (Hirofumi.FUJII@kek.jp) * * Status * Public Domain * * History * 07-Jun-1996 1st draft version * * Compile/Link * MS VC++ 4.0J * cl /MT nvt.c wsock32.lib * * References * RFC 854 (Telnet Protocol Specification) * RFC 855 (Telnet Option Specifications) * RFC 856 (Telnet Binary Transmission) * RFC 857 (Telnet Echo Option) * RFC 858 (Telnet Suppress Go Ahead Option) * RFC 859 (Telnet Status Option) * RFC 860 (Telnet Timing Mark Option) * RFC 861 (Telnet Extended Options - List Option) * */ #define STRICT #include #include #include #include #include #include #include /* Definitions */ #define TELNET_SE 240 #define TELNET_NOP 241 #define TELNET_DM 242 #define TELNET_BRK 243 #define TELNET_IP 244 #define TELNET_AO 245 #define TELNET_AYT 246 #define TELNET_EC 247 #define TELNET_EL 248 #define TELNET_GA 249 #define TELNET_SB 250 #define TELNET_WILL 251 #define TELNET_WONT 252 #define TELNET_DO 253 #define TELNET_DONT 254 #define TELNET_IAC 255 #define TELOPT_ECHO 1 #define TELOPT_SUPP 3 #define TELOPT_STATUS 5 #define TELOPT_TM 6 #define TELOPT_EXOPL 255 /* Prototypes */ void main( int argc, char *argv[] ); /* Thread 1 */ void RecvProc( void* ); /* Thread 2 */ /* Global Variables */ HANDLE hScreenMutex; HANDLE hSendSockMutex; int RunFlag; HANDLE hRunMutex; SOCKET sockfd; /* Body */ int netstart( void ) { WSADATA wsadata; WORD wsaversion; wsaversion = 0x0101; return( WSAStartup( wsaversion, &wsadata ) ); } void netclose( SOCKET sockfd ) { closesocket( sockfd ); WSACleanup(); return; } void main( int argc, char *argv[] ) { unsigned long inaddr; struct hostent *hp; struct sockaddr_in serv_addr; short remoteport; int cont; int n; int Keycode; char ch; /* Check the number of arguments */ if( (argc != 2) && (argc != 3) ) { fprintf( stderr, "Usage: %s hostname [port]\n", argv[0] ); return; } /* Start network module */ if( netstart() != 0 ) { fprintf( stderr, "Cannot start the network.\n" ); return; } /* Clear the server address */ memset( (char *)&serv_addr, 0, sizeof( serv_addr ) ); /* Get the server address */ if( (inaddr = inet_addr( argv[1] )) != INADDR_NONE ) { /* OK, It's dotted-decimal format */ memcpy( (char *)&serv_addr.sin_addr, (char *)&inaddr, sizeof( inaddr ) ); } else { /* Try to get hostaddress by using gethostbyname */ if( (hp = gethostbyname( argv[1] )) == NULL ) { WSACleanup(); fprintf( stderr, "Error to get the hostaddress of %s\n", argv[1] ); return; } memcpy( (char *)&serv_addr.sin_addr, hp->h_addr, hp->h_length ); } if( argc == 2 ) remoteport = IPPORT_TELNET; else remoteport = atoi( argv[2] ); serv_addr.sin_port = htons( remoteport ); serv_addr.sin_family = AF_INET; /* Create TCP socket */ if( (sockfd = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET ) { WSACleanup(); fprintf( stderr, "Cannot create TCP socket\n" ); return; } fprintf( stderr, "Trying %s...\n", inet_ntoa( serv_addr.sin_addr ) ); /* Connet to the server */ if( connect( sockfd, (struct sockaddr *)&serv_addr, sizeof( serv_addr ) ) < 0 ) { netclose( sockfd ); fprintf( stderr, "Cannot connect to the server\n" ); return; } fprintf( stderr, "Connected to %s.\n", argv[1] ); fprintf( stderr, "Escape character is '^]'.\n" ); /* Create Mutex */ hScreenMutex = CreateMutex( NULL, TRUE, NULL ); hSendSockMutex = CreateMutex( NULL, TRUE, NULL ); hRunMutex = CreateMutex( NULL, TRUE, NULL ); cont = RunFlag = -1; ReleaseMutex( hScreenMutex ); ReleaseMutex( hSendSockMutex ); ReleaseMutex( hRunMutex ); _beginthread( RecvProc, 0, NULL ); while( cont ) { Keycode = _getch(); if( Keycode == 0x1d ) { WaitForSingleObject( hRunMutex, INFINITE ); RunFlag = 0; ReleaseMutex( hRunMutex ); } else { ch = Keycode; WaitForSingleObject( hRunMutex, INFINITE ); cont = RunFlag; ReleaseMutex( hRunMutex ); if( cont ) { WaitForSingleObject( hSendSockMutex, INFINITE ); n = send( sockfd, &ch, 1, 0 ); ReleaseMutex( hSendSockMutex ); if( n != 1 ) { WaitForSingleObject( hScreenMutex, INFINITE ); fprintf( stderr, "Send Error\n" ); ReleaseMutex( hScreenMutex ); WaitForSingleObject( hRunMutex, INFINITE ); cont = RunFlag = 0; } } } WaitForSingleObject( hRunMutex, INFINITE ); cont = RunFlag; ReleaseMutex( hRunMutex ); } /* All Done */ CloseHandle( hRunMutex ); CloseHandle( hSendSockMutex ); CloseHandle( hScreenMutex ); } void SendTelOpt( unsigned int cmd, unsigned int opt ) { unsigned char ch[3]; ch[0] = TELNET_IAC; ch[1] = cmd; ch[2] = opt; WaitForSingleObject( hSendSockMutex, INFINITE ); send( sockfd, ch, 3, 0 ); ReleaseMutex( hSendSockMutex ); } void RecvProc( void* p ) { unsigned char ch; unsigned int c; unsigned int uIACcmd; unsigned int uIACopt; int n; int inIAC; inIAC = 0; while( (n = recv( sockfd, &ch, 1, 0 )) == 1 ) { if( ch == 0xff ) { if( inIAC ) { WaitForSingleObject( hScreenMutex, INFINITE ); c = ch; fputc( c, stdout ); inIAC = 0; } else { inIAC = 1; } } else { if( inIAC ) { if( inIAC == 1 ) { uIACcmd = ch; inIAC++; } else { uIACopt = ch; if( uIACcmd == TELNET_WILL ) { if( (uIACopt == TELOPT_ECHO) || (uIACopt == TELOPT_SUPP) ) { SendTelOpt( TELNET_DO, uIACopt ); } else { SendTelOpt( TELNET_DONT, uIACopt ); } } else if( uIACcmd == TELNET_DO ) { SendTelOpt( TELNET_WONT, uIACopt ); } inIAC = 0; } } else { WaitForSingleObject( hScreenMutex, INFINITE ); c = ch; if( c != 0 ) fputc( c, stdout ); ReleaseMutex( hScreenMutex ); } } } WaitForSingleObject( hRunMutex, INFINITE ); RunFlag = 0; ReleaseMutex( hRunMutex ); WaitForSingleObject( hScreenMutex, INFINITE ); fprintf( stderr, "Connection closed\n" ); ReleaseMutex( hScreenMutex ); }