Commit 40d829f2 authored by rswindell's avatar rswindell

Auto-detect non-Telnet connections to the terminal server's Telnet port and

automatically revert to Raw/TCP mode. This resolves the issue of users that
connect using modem/serial emulators over TCP that do not actually support Telnet and then either try to transfer files, which usually will not work due to escaped (or unescaped) IAC (0xFF) characters, or the user may be sent Telnet Go Ahead (GA) sequences which may display as periodic garbage in their terminal program.

This seemed like a better solution than having (yet another) dedicated terminal server port for "raw" connections over TCP, though a "raw" port still might not be a bad idea for a future enhancement. RLogin is already super close to "raw", so it's probably not really necessary to have another port configured/listening.
parent eddb8b75
......@@ -411,45 +411,54 @@ bool sbbs_t::answer()
/* Stop the input thread from writing to the telnet_* vars */
pthread_mutex_lock(&input_thread_mutex);
if(stricmp(telnet_terminal,"sexpots")==0) { /* dial-up connection (via SexPOTS) */
SAFEPRINTF2(str,"%s connection detected at %lu bps", terminal, cur_rate);
logline("@S",str);
node_connection = (ushort)cur_rate;
SAFEPRINTF(connection,"%lu",cur_rate);
SAFECOPY(cid,"Unknown");
SAFECOPY(client_name,"Unknown");
if(telnet_location[0]) { /* Caller-ID info provided */
SAFEPRINTF(str, "CID: %s", telnet_location);
logline("@*",str);
SAFECOPY(cid,telnet_location);
truncstr(cid," "); /* Only include phone number in CID */
char* p=telnet_location;
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
if(*p) {
SAFECOPY(client_name,p); /* CID name, if provided (maybe 'P' or 'O' if private or out-of-area) */
if(telnet_cmds_received) {
if(stricmp(telnet_terminal,"sexpots")==0) { /* dial-up connection (via SexPOTS) */
SAFEPRINTF2(str,"%s connection detected at %lu bps", terminal, cur_rate);
logline("@S",str);
node_connection = (ushort)cur_rate;
SAFEPRINTF(connection,"%lu",cur_rate);
SAFECOPY(cid,"Unknown");
SAFECOPY(client_name,"Unknown");
if(telnet_location[0]) { /* Caller-ID info provided */
SAFEPRINTF(str, "CID: %s", telnet_location);
logline("@*",str);
SAFECOPY(cid,telnet_location);
truncstr(cid," "); /* Only include phone number in CID */
char* p=telnet_location;
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
if(*p) {
SAFECOPY(client_name,p); /* CID name, if provided (maybe 'P' or 'O' if private or out-of-area) */
}
}
SAFECOPY(client.addr,cid);
SAFECOPY(client.host,client_name);
client_on(client_socket,&client,TRUE /* update */);
} else {
if(telnet_location[0]) { /* Telnet Location info provided */
lprintf(LOG_INFO, "Telnet Location: %s", telnet_location);
SAFECOPY(cid, telnet_location);
}
}
SAFECOPY(client.addr,cid);
SAFECOPY(client.host,client_name);
client_on(client_socket,&client,TRUE /* update */);
} else {
if(telnet_location[0]) { /* Telnet Location info provided */
lprintf(LOG_INFO, "Telnet Location: %s", telnet_location);
SAFECOPY(cid, telnet_location);
if(telnet_speed) {
lprintf(LOG_INFO, "Telnet Speed: %lu bps", telnet_speed);
cur_rate = telnet_speed;
cur_cps = telnet_speed/10;
}
if(telnet_terminal[0])
SAFECOPY(terminal, telnet_terminal);
if(telnet_cols >= TERM_COLS_MIN && telnet_cols <= TERM_COLS_MAX)
cols = telnet_cols;
if(telnet_rows >= TERM_ROWS_MIN && telnet_rows <= TERM_ROWS_MAX)
rows = telnet_rows;
} else {
lprintf(LOG_NOTICE, "no Telnet commands received, reverting to Raw/TCP mode);
telnet_mode |= TELNET_MODE_OFF;
client.protocol = "Raw";
client_on(client_socket, &client,/* update: */true);
SAFECOPY(connection, client.protocol);
node_connection = NODE_CONNECTION_RAW;
}
if(telnet_speed) {
lprintf(LOG_INFO, "Telnet Speed: %lu bps", telnet_speed);
cur_rate = telnet_speed;
cur_cps = telnet_speed/10;
}
if(telnet_terminal[0])
SAFECOPY(terminal, telnet_terminal);
if(telnet_cols >= TERM_COLS_MIN && telnet_cols <= TERM_COLS_MAX)
cols = telnet_cols;
if(telnet_rows >= TERM_ROWS_MIN && telnet_rows <= TERM_ROWS_MAX)
rows = telnet_rows;
pthread_mutex_unlock(&input_thread_mutex);
}
lprintf(LOG_INFO, "terminal type: %lux%lu %s", cols, rows, terminal);
......
......@@ -430,6 +430,8 @@ static char* node_connection_desc(sbbs_t* sbbs, ushort conn, char* str)
return sbbs->text[NodeConnectionRLogin];
case NODE_CONNECTION_SSH:
return sbbs->text[NodeConnectionSSH];
case NODE_CONNECTION_RAW:
return sbbs->text[NodeConnectionRaw];
default:
sprintf(str,sbbs->text[NodeConnectionModem],conn);
break;
......
......@@ -1551,7 +1551,7 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
else if(sbbs->telnet_cmdlen>=2 && command==TELNET_SB) {
if(inbuf[i]==TELNET_SE
&& sbbs->telnet_cmd[sbbs->telnet_cmdlen-2]==TELNET_IAC) {
sbbs->telnet_cmds_received++;
if(startup->options&BBS_OPT_DEBUG_TELNET)
lprintf(LOG_DEBUG,"Node %d %s telnet sub-negotiation command: %s (%u bytes)"
,sbbs->cfg.node_num
......@@ -1655,6 +1655,7 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
}
} // Sub-negotiation command
else if(sbbs->telnet_cmdlen==2 && inbuf[i]<TELNET_WILL) {
sbbs->telnet_cmds_received++;
if(startup->options&BBS_OPT_DEBUG_TELNET)
lprintf(LOG_DEBUG,"Node %d %s telnet cmd: %s"
,sbbs->cfg.node_num
......@@ -1663,7 +1664,7 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
sbbs->telnet_cmdlen=0;
}
else if(sbbs->telnet_cmdlen>=3) { /* telnet option negotiation */
sbbs->telnet_cmds_received++;
if(startup->options&BBS_OPT_DEBUG_TELNET)
lprintf(LOG_DEBUG,"Node %d %s telnet cmd: %s %s"
,sbbs->cfg.node_num
......@@ -3347,6 +3348,7 @@ sbbs_t::sbbs_t(ushort node_num, union xp_sockaddr *addr, size_t addr_len, const
telnet_cols=0;
telnet_rows=0;
telnet_speed=0;
telnet_cmds_received = 0;
rlogin_name[0]=0;
rlogin_pass[0]=0;
rlogin_term[0]=0;
......
......@@ -232,6 +232,9 @@ static char* node_connection_desc(ushort conn, char* str)
case NODE_CONNECTION_SSH:
strcpy(str,"via ssh");
break;
case NODE_CONNECTION_RAW:
strcpy(str,"via raw");
break;
default:
sprintf(str,"at %ubps",conn);
break;
......
......@@ -123,6 +123,7 @@ typedef struct _PACK { /* Node information kept in node.dab */
#define NODE_CONNECTION_TELNET USHRT_MAX /* 0xffff */
#define NODE_CONNECTION_RLOGIN (USHRT_MAX-1)
#define NODE_CONNECTION_SSH (USHRT_MAX-2)
#define NODE_CONNECTION_RAW (USHRT_MAX-3)
misc, /* Miscellaneous bits for node */
aux; /* Auxillary word for node */
uint32_t extaux; /* Extended aux dword for node */
......
......@@ -377,8 +377,9 @@ public:
void send_telnet_cmd(uchar cmd, uchar opt);
bool request_telnet_opt(uchar cmd, uchar opt, unsigned waitforack=0);
uchar telnet_cmd[64];
uint telnet_cmdlen;
uchar telnet_cmd[64];
uint telnet_cmdlen;
ulong telnet_cmds_received;
ulong telnet_mode;
/* input_thread() writes to these variables: */
uchar telnet_last_rxch;
......
......@@ -840,6 +840,7 @@ enum {
,QWKSettingsUtf8
,MsgPostedToYouVia
,Unlimited
,NodeConnectionRaw
,TOTAL_TEXT
};
......
......@@ -1371,4 +1371,5 @@ const char * const text_defaults[TOTAL_TEXT]={
,"\x01\x6e\x01\x6d\x01\x68\x25\x73\x01\x6e\x01\x6d\x25\x2e\x30\x73\x20\x70\x6f\x73\x74\x65\x64\x20\x74\x6f\x20\x79\x6f\x75\x20\x6f"
"\x6e\x20\x01\x68\x25\x73\x20\x01\x6e\x01\x6d\x25\x73\x0d\x0a" // 828 MsgPostedToYouVia
,"\x75\x6e\x6c\x69\x6d\x69\x74\x65\x64" // 829 Unlimited
,"\x20\x76\x69\x61\x20\x72\x61\x77" // 830 NodeConnectionRaw
};
......@@ -952,6 +952,9 @@ static char* node_connection_desc(ushort conn, char* str)
case NODE_CONNECTION_SSH:
strcpy(str,"via ssh");
break;
case NODE_CONNECTION_RAW:
strcpy(str,"via raw");
break;
default:
sprintf(str,"at %ubps",conn);
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment