Added experimental telnet outbound code

This commit is contained in:
Michiel Broek 2004-01-31 22:15:00 +00:00
parent 3b852d7c3f
commit 84e0e3974b
8 changed files with 313 additions and 39 deletions

View File

@ -2,6 +2,10 @@ $Id$
v0.39.9 29-Jan-2004
mbcico:
Added experimental code for telnet outbound connections. This
code is not compiled by default so don't worry or bother.
v0.39.8 26-Jan-2004 - 29-Jan-2004

2
TODO
View File

@ -124,6 +124,8 @@ mbcico:
N: Implement PLZ turn off m_get command.
N: Make workaround for binkp bug in Irex 2.24 upto 2.29
mbfile:
L: Add a check to see if the magic filenames are (still) valid.

View File

@ -86,6 +86,7 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#include <pthread.h>
#pragma pack(1)

View File

@ -181,9 +181,11 @@ int call(faddr *addr)
tcp_mode = TCPMODE_IBN;
} else if (strcmp(protocol, "fido") == 0) {
tcp_mode = TCPMODE_IFC;
// } else if (strcmp(protocol, "telnet") == 0) {
// tcp_mode = TCPMODE_ITN;
// telnet = TRUE;
#ifdef USE_EXPERIMENT
} else if (strcmp(protocol, "telnet") == 0) {
tcp_mode = TCPMODE_ITN;
telnet = TRUE;
#endif
} else {
Syslog('+', "No common TCP/IP protocols for node %s", nlent->name);
free(inetaddr);

View File

@ -369,11 +369,17 @@ int main(int argc, char *argv[])
/*
* Slave (answer) mode
*/
#ifdef USE_EXPERIMENT
if (telnet) {
Syslog('-', "Will use experimental telnet code");
}
#else
if (telnet) {
WriteError("Answering calls with the \"-t itn\" option no longer supported");
WriteError("Install mbtelind to answer incoming telnet calls");
die(MBERR_COMMANDLINE);
}
#endif
if (!answermode && tcp_mode == TCPMODE_IBN)
answermode = xstrcpy((char *)"ibn");
rc = maxrc = answer(answermode);

View File

@ -61,6 +61,13 @@ extern long rcvdbytes;
extern int Loaded;
static int tcp_is_open = FALSE;
#ifdef USE_EXPERIMENT
void telnet_init(int);
void telnet_answer(int, int, int);
void telout_filter(int [], int);
void telin_filter(int [], int);
#endif
/* opentcp() was rewritten by Martin Junius */
@ -68,10 +75,12 @@ int opentcp(char *name)
{
struct servent *se;
struct hostent *he;
int a1, a2, a3, a4, Fd, GotPort = FALSE;
struct sockaddr_in server;
int a1, a2, a3, a4, rc, Fd, Fdo, GotPort = FALSE;
char *errmsg, *portname;
short portnum;
struct sockaddr_in server;
int input_pipe[2], output_pipe[2];
pid_t fpid;
Syslog('+', "Open TCP connection to \"%s\"", MBSE_SS(name));
@ -102,11 +111,13 @@ int opentcp(char *name)
else
server.sin_port = htons(FIDOPORT);
break;
// case TCPMODE_ITN: if ((se = getservbyname("telnet", "tcp")))
// server.sin_port = se->s_port;
// else
// server.sin_port = htons(TELNPORT);
// break;
#ifdef USE_EXPERIMENT
case TCPMODE_ITN: if ((se = getservbyname("telnet", "tcp")))
server.sin_port = se->s_port;
else
server.sin_port = htons(TELNPORT);
break;
#endif
case TCPMODE_IBN: if ((se = getservbyname("binkd", "tcp")))
server.sin_port = se->s_port;
else
@ -134,38 +145,134 @@ int opentcp(char *name)
return -1;
}
Syslog('d', "SIGPIPE => sigpipe()");
signal(SIGPIPE, sigpipe);
Syslog('d', "SIGHUP => linedrop()");
signal(SIGHUP, linedrop);
fflush(stdin);
fflush(stdout);
setbuf(stdin,NULL);
setbuf(stdout,NULL);
close(0);
close(1);
if ((Fd = socket(AF_INET,SOCK_STREAM,0)) != 0) {
WriteError("$Cannot create socket (got %d, expected 0");
open("/dev/null",O_RDONLY);
open("/dev/null",O_WRONLY);
return -1;
}
if (dup(Fd) != 1) {
WriteError("$Cannot dup socket");
open("/dev/null",O_WRONLY);
return -1;
}
clearerr(stdin);
clearerr(stdout);
if (connect(Fd,(struct sockaddr *)&server,sizeof(server)) == -1) {
Syslog('+', "Cannot connect %s",inet_ntoa(server.sin_addr));
return -1;
}
#ifdef USE_EXPERIMENT
if (tcp_mode == TCPMODE_ITN) {
Syslog('s', "Installing telnet filter...");
f_flags=0;
Syslog('d', "SIGPIPE => sigpipe()");
signal(SIGPIPE, sigpipe);
Syslog('d', "SIGHUP => linedrop()");
signal(SIGHUP, linedrop);
/*
* Create TCP socket and open
*/
if ((Fdo = socket(AF_INET,SOCK_STREAM,0)) == -1) {
WriteError("$Cannot create socket");
return -1;
}
if (connect(Fdo,(struct sockaddr *)&server,sizeof(server)) == -1) {
Syslog('+', "Cannot connect %s",inet_ntoa(server.sin_addr));
return -1;
}
Syslog('s', "socket %d", Fdo);
fflush(stdin);
fflush(stdout);
setbuf(stdin,NULL);
setbuf(stdout, NULL);
close(0);
close(1);
/*
* Create output pipe
*/
if ((rc = pipe(output_pipe)) == -1) {
WriteError("$could not create output_pipe");
return -1;
}
fpid = fork();
switch (fpid) {
case -1: WriteError("fork for telout_filter failed");
return -1;
case 0: if (close(output_pipe[1]) == -1) {
WriteError("$error close output_pipe[1]");
return -1;
}
telout_filter(output_pipe, Fdo);
/* NOT REACHED */
}
if (close(output_pipe[0] == -1)) {
WriteError("$error close output_pipe[0]");
return -1;
}
Syslog('s', "telout_filter forked with pid %d", fpid);
/*
* Create input pipe
*/
if ((rc = pipe(input_pipe)) == -1) {
WriteError("$could not create input_pipe");
return -1;
}
/*
* Fork input filter
*/
fpid = fork();
switch (fpid) {
case -1: WriteError("fork for telin_filter failed");
return -1;
case 0: if (close(input_pipe[0]) == -1) {
WriteError("$error close input_pipe[0]");
return -1;
}
telin_filter(input_pipe, Fdo);
/* NOT REACHED */
}
if (close(input_pipe[1]) == -1) {
WriteError("$error close input_pipe[1]");
return -1;
}
Syslog('s', "telin_filter forked with pid %d", fpid);
Syslog('s', "stdout = %d", output_pipe[1]);
Syslog('s', "stdin = %d", input_pipe[0]);
telnet_init(Fdo);
f_flags=0;
} else {
#endif
/*
* Transparant 8 bits connection
*/
Syslog('d', "SIGPIPE => sigpipe()");
signal(SIGPIPE, sigpipe);
Syslog('d', "SIGHUP => linedrop()");
signal(SIGHUP, linedrop);
fflush(stdin);
fflush(stdout);
setbuf(stdin,NULL);
setbuf(stdout,NULL);
close(0);
close(1);
if ((Fd = socket(AF_INET,SOCK_STREAM,0)) != 0) {
WriteError("$Cannot create socket (got %d, expected 0)", Fd);
open("/dev/null",O_RDONLY);
open("/dev/null",O_WRONLY);
return -1;
}
if (dup(Fd) != 1) {
WriteError("$Cannot dup socket");
open("/dev/null",O_WRONLY);
return -1;
}
clearerr(stdin);
clearerr(stdout);
if (connect(Fd,(struct sockaddr *)&server,sizeof(server)) == -1) {
Syslog('+', "Cannot connect %s",inet_ntoa(server.sin_addr));
return -1;
}
f_flags=0;
#ifdef USE_EXPERIMENT
}
#endif
Syslog('+', "Established %s/TCP connection with %s, port %d",
(tcp_mode == TCPMODE_IFC) ? "IFC":(tcp_mode == TCPMODE_IBN) ? "IBN":"Unknown",
(tcp_mode == TCPMODE_IFC) ? "IFC":(tcp_mode == TCPMODE_ITN) ?"ITN":(tcp_mode == TCPMODE_IBN) ? "IBN":"Unknown",
inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port));
c_start = time(NULL);
carrier = TRUE;
@ -183,6 +290,14 @@ void closetcp(void)
if (!tcp_is_open)
return;
#ifdef USE_EXPERIMENT
if (tcp_mode == TCPMODE_ITN) {
/*
* Check if telout thread is running
*/
}
#endif
shutdown(fd, 2);
Syslog('d', "SIGHUP => SIG_IGN");
signal(SIGHUP, SIG_IGN);
@ -218,3 +333,135 @@ void closetcp(void)
}
#ifdef USE_EXPERIMENT
void telnet_init(int Fd)
{
Syslog('s', "telnet_init(%d)", Fd);
telnet_answer(DO, TOPT_SUPP, Fd);
telnet_answer(WILL, TOPT_SUPP, Fd);
telnet_answer(DO, TOPT_BIN, Fd);
telnet_answer(WILL, TOPT_BIN, Fd);
telnet_answer(DO, TOPT_ECHO, Fd);
telnet_answer(WILL, TOPT_ECHO, Fd);
}
void telnet_answer(int tag, int opt, int Fd)
{
char buf[3];
char *r = (char *)"???";
switch (tag) {
case WILL: r = (char *)"WILL";
break;
case WONT: r = (char *)"WONT";
break;
case DO: r = (char *)"DO";
break;
case DONT: r = (char *)"DONT";
break;
}
Syslog('s', "Telnet: send %s %d", r, opt);
buf[0] = IAC;
buf[1] = tag;
buf[2] = opt;
if (write (Fd, buf, 3) != 3)
WriteError("$answer cant send");
}
void telout_filter(int output_pipe[], int Fd)
{
int rc, c;
char ch;
Syslog('s', "telout_filter: in=%d out=%d", output_pipe[0], Fd);
while (read(output_pipe[0], &ch, 1) > 0) {
c = (int)ch & 0xff;
// Syslog('s', "telout_filter: ch=%s", printablec(c));
if (c == IAC) {
Syslog('s', "telout_filter: got IAC");
/*
* Escape IAC characters
*/
rc = write(Fd, &ch, 1);
}
/* write translated character back to user_handler. */
rc = write(Fd, &ch, 1);
if (rc == -1) { /* write failed - notify user and exit. */
Syslog('s', "$telout_filter: write to Fd failed");
exit(1);
}
}
Syslog('s', "$telout_filter: read error");
exit(0);
}
void telin_filter(int input_pipe[], int Fd)
{
int rc, c, m;
char ch;
Syslog('s', "telin_filter: in=%d out=%d", Fd, input_pipe[1]);
Syslog('s', "telin_filter: IAC=%s %d", printablec(IAC), IAC);
while (read(Fd, &ch, 1) > 0) {
c = (int)ch & 0xff;
// Syslog('s', "telin_filter: ch=%s", printablec(c));
if (c == IAC) {
Syslog('s', "got IAC");
if ((read(Fd, &ch, 1) < 0))
break;
m = (int)ch & 0xff;
switch (m) {
case WILL: read(Fd, &ch, 1);
m = (int)ch & 0xff;
Syslog('s', "Telnet: recv WILL %d", m);
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
telnet_answer(DONT, m, input_pipe[1]);
break;
case WONT: read(Fd, &ch, 1);
m = (int)ch & 0xff;
Syslog('s', "Telnet: recv WONT %d", m);
break;
case DO: read(Fd, &ch, 1);
m = (int)ch & 0xff;
Syslog('s', "Telnet: recv DO %d", m);
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
telnet_answer(WONT, m, input_pipe[1]);
break;
case DONT: read(Fd, &ch, 1);
m = (int)ch & 0xff;
Syslog('s', "Telnet: recv DONT %d", m);
break;
case IAC: ch = (char)m & 0xff;
rc = write(input_pipe[1], &ch, 1);
break;
default: Syslog('s', "Telnet: recv IAC %d, not good", m);
break;
}
} else {
// Syslog('s', "Telnet: normal");
ch = (char)c;
rc = write(input_pipe[1], &ch, 1);
if (rc == -1) { /* write failed - notify user and exit. */
Syslog('s', "$telin_filter: write to input_pipe[1] failed");
exit(1);
}
}
}
Syslog('s', "$telin_filter: read error");
exit(0);
}
#endif

View File

@ -3,6 +3,13 @@
#ifndef _OPENTCP_H
#define _OPENTCP_H
#define MBT_TIMEOUT 500
#define MBT_BUFLEN 8192
#define TOPT_BIN 0
#define TOPT_ECHO 1
#define TOPT_SUPP 3
int opentcp(char *);
void closetcp(void);

View File

@ -110,6 +110,11 @@ int session(faddr *a, node *nl, int role, int tp, char *dt)
}
}
session_flags |= SESSION_TCP;
#ifdef USE_EXPERIMENT
if ((tcp_mode == TCPMODE_ITN) && (role == 0)) {
Syslog('-', "Will need to install telnet receiver thread");
}
#endif
}
if (data)