Added experimental telnet outbound code
This commit is contained in:
parent
3b852d7c3f
commit
84e0e3974b
@ -2,6 +2,10 @@ $Id$
|
|||||||
|
|
||||||
v0.39.9 29-Jan-2004
|
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
|
v0.39.8 26-Jan-2004 - 29-Jan-2004
|
||||||
|
|
||||||
|
2
TODO
2
TODO
@ -124,6 +124,8 @@ mbcico:
|
|||||||
|
|
||||||
N: Implement PLZ turn off m_get command.
|
N: Implement PLZ turn off m_get command.
|
||||||
|
|
||||||
|
N: Make workaround for binkp bug in Irex 2.24 upto 2.29
|
||||||
|
|
||||||
mbfile:
|
mbfile:
|
||||||
L: Add a check to see if the magic filenames are (still) valid.
|
L: Add a check to see if the magic filenames are (still) valid.
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
#ifdef HAVE_ZLIB_H
|
#ifdef HAVE_ZLIB_H
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
@ -181,9 +181,11 @@ int call(faddr *addr)
|
|||||||
tcp_mode = TCPMODE_IBN;
|
tcp_mode = TCPMODE_IBN;
|
||||||
} else if (strcmp(protocol, "fido") == 0) {
|
} else if (strcmp(protocol, "fido") == 0) {
|
||||||
tcp_mode = TCPMODE_IFC;
|
tcp_mode = TCPMODE_IFC;
|
||||||
// } else if (strcmp(protocol, "telnet") == 0) {
|
#ifdef USE_EXPERIMENT
|
||||||
// tcp_mode = TCPMODE_ITN;
|
} else if (strcmp(protocol, "telnet") == 0) {
|
||||||
// telnet = TRUE;
|
tcp_mode = TCPMODE_ITN;
|
||||||
|
telnet = TRUE;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Syslog('+', "No common TCP/IP protocols for node %s", nlent->name);
|
Syslog('+', "No common TCP/IP protocols for node %s", nlent->name);
|
||||||
free(inetaddr);
|
free(inetaddr);
|
||||||
|
@ -369,11 +369,17 @@ int main(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
* Slave (answer) mode
|
* Slave (answer) mode
|
||||||
*/
|
*/
|
||||||
|
#ifdef USE_EXPERIMENT
|
||||||
|
if (telnet) {
|
||||||
|
Syslog('-', "Will use experimental telnet code");
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (telnet) {
|
if (telnet) {
|
||||||
WriteError("Answering calls with the \"-t itn\" option no longer supported");
|
WriteError("Answering calls with the \"-t itn\" option no longer supported");
|
||||||
WriteError("Install mbtelind to answer incoming telnet calls");
|
WriteError("Install mbtelind to answer incoming telnet calls");
|
||||||
die(MBERR_COMMANDLINE);
|
die(MBERR_COMMANDLINE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!answermode && tcp_mode == TCPMODE_IBN)
|
if (!answermode && tcp_mode == TCPMODE_IBN)
|
||||||
answermode = xstrcpy((char *)"ibn");
|
answermode = xstrcpy((char *)"ibn");
|
||||||
rc = maxrc = answer(answermode);
|
rc = maxrc = answer(answermode);
|
||||||
|
319
mbcico/opentcp.c
319
mbcico/opentcp.c
@ -61,6 +61,13 @@ extern long rcvdbytes;
|
|||||||
extern int Loaded;
|
extern int Loaded;
|
||||||
static int tcp_is_open = FALSE;
|
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 */
|
/* opentcp() was rewritten by Martin Junius */
|
||||||
|
|
||||||
@ -68,10 +75,12 @@ int opentcp(char *name)
|
|||||||
{
|
{
|
||||||
struct servent *se;
|
struct servent *se;
|
||||||
struct hostent *he;
|
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;
|
char *errmsg, *portname;
|
||||||
short portnum;
|
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));
|
Syslog('+', "Open TCP connection to \"%s\"", MBSE_SS(name));
|
||||||
|
|
||||||
@ -102,11 +111,13 @@ int opentcp(char *name)
|
|||||||
else
|
else
|
||||||
server.sin_port = htons(FIDOPORT);
|
server.sin_port = htons(FIDOPORT);
|
||||||
break;
|
break;
|
||||||
// case TCPMODE_ITN: if ((se = getservbyname("telnet", "tcp")))
|
#ifdef USE_EXPERIMENT
|
||||||
// server.sin_port = se->s_port;
|
case TCPMODE_ITN: if ((se = getservbyname("telnet", "tcp")))
|
||||||
// else
|
server.sin_port = se->s_port;
|
||||||
// server.sin_port = htons(TELNPORT);
|
else
|
||||||
// break;
|
server.sin_port = htons(TELNPORT);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case TCPMODE_IBN: if ((se = getservbyname("binkd", "tcp")))
|
case TCPMODE_IBN: if ((se = getservbyname("binkd", "tcp")))
|
||||||
server.sin_port = se->s_port;
|
server.sin_port = se->s_port;
|
||||||
else
|
else
|
||||||
@ -134,38 +145,134 @@ int opentcp(char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Syslog('d', "SIGPIPE => sigpipe()");
|
#ifdef USE_EXPERIMENT
|
||||||
signal(SIGPIPE, sigpipe);
|
if (tcp_mode == TCPMODE_ITN) {
|
||||||
Syslog('d', "SIGHUP => linedrop()");
|
Syslog('s', "Installing telnet filter...");
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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",
|
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));
|
inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port));
|
||||||
c_start = time(NULL);
|
c_start = time(NULL);
|
||||||
carrier = TRUE;
|
carrier = TRUE;
|
||||||
@ -183,6 +290,14 @@ void closetcp(void)
|
|||||||
if (!tcp_is_open)
|
if (!tcp_is_open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef USE_EXPERIMENT
|
||||||
|
if (tcp_mode == TCPMODE_ITN) {
|
||||||
|
/*
|
||||||
|
* Check if telout thread is running
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
shutdown(fd, 2);
|
shutdown(fd, 2);
|
||||||
Syslog('d', "SIGHUP => SIG_IGN");
|
Syslog('d', "SIGHUP => SIG_IGN");
|
||||||
signal(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
|
||||||
|
@ -3,6 +3,13 @@
|
|||||||
#ifndef _OPENTCP_H
|
#ifndef _OPENTCP_H
|
||||||
#define _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 *);
|
int opentcp(char *);
|
||||||
void closetcp(void);
|
void closetcp(void);
|
||||||
|
|
||||||
|
@ -110,6 +110,11 @@ int session(faddr *a, node *nl, int role, int tp, char *dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
session_flags |= SESSION_TCP;
|
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)
|
if (data)
|
||||||
|
Reference in New Issue
Block a user