|
|
|
@@ -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
|
|
|
|
|