Hi FreeBSD experts,
I wrote a VERY simple telnet program that actually works as a Network Virtual Terminal. It is achieved by sending "WON'T XXX" to all "DO XXX" server requests. It should work according to RFC-854, page 4: "Since the NVT is what is left when no options are enabled, the DON'T and WON'T responses are guaranteed to leave the connection in a state which both ends can handle." It works with Unix, Linux, Windows, Cisco, but not with my FreeBSD: after a while it stops sending anything. This is the attempt trace:
Internet Protocol, Src Addr: 10.1.1.223 (10.1.1.223), Dst Addr: 10.1.1.222 (10.1.1.222)
Telnet
Command: Do Authentication Option
Internet Protocol, Src Addr: 10.1.1.222 (10.1.1.222), Dst Addr: 10.1.1.223 (10.1.1.223)
Telnet
Command: Do Echo
Command: Won't Authentication Option
Internet Protocol, Src Addr: 10.1.1.223 (10.1.1.223), Dst Addr: 10.1.1.222 (10.1.1.222)
Telnet
Command: Will Echo
Command: Will Encryption Option
Command: Do Terminal Type
Command: Do Terminal Speed
Command: Do X Display Location
Command: Do New Environment Option
Command: Do Environment Option
Internet Protocol, Src Addr: 10.1.1.222 (10.1.1.222), Dst Addr: 10.1.1.223 (10.1.1.223)
Telnet
Command: Won't Terminal Type
Command: Won't Terminal Speed
Command: Won't X Display Location
Command: Won't New Environment Option
Command: Won't Environment Option
Can you tell me why it does not work, and what can I do to make it work?
Thank you for all hints!
Regards,
Zacco
----------
This is the very first experimental code:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
char* hostname = "hostname";
char* pwd = "password\r\n";
char* usr = "username\r\n";
bool opt0 = true;
bool isLogged = false;
void SndMsg( int sd, const char* mp )
{
send( sd, mp, strlen(mp), 0 );
printf( "\nsend msg: %s\n", mp );
}
bool Telnet_recv( int socket_desc )
{
unsigned char optmsg[100];
int bufsize = 1024;
unsigned char buffer[bufsize];
int length = recv(socket_desc, buffer, bufsize, 0);
int optmsglen = 0;
if( opt0 )
{
optmsg[optmsglen] = 255;
optmsg[optmsglen+1] = 253;
optmsg[optmsglen+2] = 1;
optmsglen += 3;
opt0 = false;
}
for (int i = 0; i < length; i += 3 )
{
if( buffer[i] == 255 ) // IAC
{
if( buffer[i+1] == 253 )
{
optmsg[optmsglen] = 255;
optmsg[optmsglen+1] = 252;
optmsg[optmsglen+2] = buffer[i+2];
optmsglen += 3;
}
}
else
{
if( (strstr( (const char*)buffer, "ogin" ) != NULL) && (!isLogged) ) { isLogged=true; SndMsg( socket_desc, usr ); }
if( strstr( (const char*)buffer, "assword") != NULL ) { isLogged = true; SndMsg( socket_desc, pwd );}
}
}
if( optmsglen > 0 ) send( socket_desc, optmsg, optmsglen, 0 );
if( buffer[length-1] == '>' || buffer[length-2] == '>' || buffer[length-2] == '#' || buffer[length-2] == '$' ) return true;
else return false;
}
int main()
{
int socket_desc;
struct hostent *he;
struct sockaddr_in address;
if( ( socket_desc=socket(AF_INET,SOCK_STREAM,0) ) == 0 ) perror( "Create socket" );
if ((he = gethostbyname( hostname )) == NULL)
{
puts("error resolving hostname..");
exit(1);
}
memcpy(&address.sin_addr, he->h_addr_list[0], he->h_length);
address.sin_family = AF_INET;
address.sin_port = htons(23);
if( connect(socket_desc, (struct sockaddr *)&address, sizeof(address)) == -1 )
{
puts("error connecting..");
exit(1);
}
int length, x = 0;
do{ printf( "\n%d. message\n", ++x ); } while( Telnet_recv( socket_desc ) );
printf( "--- Successful Login ---\n" );
close(socket_desc);
}