Attempt to make outgoing telnet work
This commit is contained in:
parent
bb1105a61f
commit
4c919784a1
@ -3,6 +3,8 @@ $Id$
|
|||||||
|
|
||||||
v0.39.2 21-Nov-2003
|
v0.39.2 21-Nov-2003
|
||||||
|
|
||||||
|
NOTE: Don't use this version yet, mbtelnetd might be removed again!
|
||||||
|
|
||||||
general:
|
general:
|
||||||
With the use of a proxy based on the iftelnetd from the ifmail
|
With the use of a proxy based on the iftelnetd from the ifmail
|
||||||
package incoming telnet sessions are now supported. Outgoing
|
package incoming telnet sessions are now supported. Outgoing
|
||||||
@ -11,9 +13,13 @@ v0.39.2 21-Nov-2003
|
|||||||
upgrade:
|
upgrade:
|
||||||
See mbtelnetd.html how to install mbtelnetd.
|
See mbtelnetd.html how to install mbtelnetd.
|
||||||
|
|
||||||
|
common.a:
|
||||||
|
A small fix in printable function.
|
||||||
|
|
||||||
mbcico:
|
mbcico:
|
||||||
If called by inetd with the -t itn parameters, mbcico aborts
|
If called by inetd with the -t itn parameters, mbcico aborts
|
||||||
and writes a short instruction in the log to install mbtelnetd.
|
and writes a short instruction in the log to install mbtelnetd.
|
||||||
|
Outgoing telnet works almost.
|
||||||
|
|
||||||
mbtelnetd:
|
mbtelnetd:
|
||||||
New program, a proxy to handle incoming telnet/vmodem sessions.
|
New program, a proxy to handle incoming telnet/vmodem sessions.
|
||||||
|
@ -497,7 +497,7 @@ char *printable(char *s, int l)
|
|||||||
case '\n': *p++='\\'; *p++='n'; break;
|
case '\n': *p++='\\'; *p++='n'; break;
|
||||||
case '\t': *p++='\\'; *p++='t'; break;
|
case '\t': *p++='\\'; *p++='t'; break;
|
||||||
case '\b': *p++='\\'; *p++='b'; break;
|
case '\b': *p++='\\'; *p++='b'; break;
|
||||||
default: sprintf(p,"\\%02x",*s); p+=3; break;
|
default: sprintf(p,"\\%02x", (*s & 0xff)); p+=3; break;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,6 @@ mbcico.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/recor
|
|||||||
outstat.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h scanout.h callstat.h outstat.h
|
outstat.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h scanout.h callstat.h outstat.h
|
||||||
nlinfo.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h nlinfo.h
|
nlinfo.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h nlinfo.h
|
||||||
mbout.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h outstat.h nlinfo.h
|
mbout.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h outstat.h nlinfo.h
|
||||||
mbtelnetd.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/mberrors.h telnio.h mbtelnetd.h
|
mbtelnetd.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/mberrors.h hydra.h telnio.h mbtelnetd.h
|
||||||
telnio.o: ../config.h ../lib/libs.h ../lib/clcomm.h telnio.h
|
telnio.o: ../config.h ../lib/libs.h ../lib/clcomm.h hydra.h telnio.h
|
||||||
# End of generated dependencies
|
# End of generated dependencies
|
||||||
|
@ -55,34 +55,18 @@
|
|||||||
#include "../lib/clcomm.h"
|
#include "../lib/clcomm.h"
|
||||||
#include "../lib/dbcfg.h"
|
#include "../lib/dbcfg.h"
|
||||||
#include "../lib/mberrors.h"
|
#include "../lib/mberrors.h"
|
||||||
|
#include "hydra.h"
|
||||||
|
#include "telnio.h"
|
||||||
#include "mbtelnetd.h"
|
#include "mbtelnetd.h"
|
||||||
|
|
||||||
|
|
||||||
#define MBT_BUFSIZ 8192
|
|
||||||
#define MBT_TIMEOUT 3600
|
#define MBT_TIMEOUT 3600
|
||||||
|
|
||||||
|
|
||||||
void die(int);
|
void die(int);
|
||||||
int init_telnet(void);
|
|
||||||
void answer(int, int);
|
|
||||||
int read0(char *, int);
|
|
||||||
int write1(char *, int);
|
|
||||||
void com_gw(int);
|
void com_gw(int);
|
||||||
|
|
||||||
|
|
||||||
#define WILL 251
|
|
||||||
#define WONT 252
|
|
||||||
#define DO 253
|
|
||||||
#define DONT 254
|
|
||||||
#define IAC 255
|
|
||||||
|
|
||||||
#define TN_TRANSMIT_BINARY 0
|
|
||||||
#define TN_ECHO 1
|
|
||||||
#define TN_SUPPRESS_GA 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tellen;
|
|
||||||
char *envptr = NULL;
|
char *envptr = NULL;
|
||||||
time_t t_start, t_end;
|
time_t t_start, t_end;
|
||||||
|
|
||||||
@ -200,11 +184,11 @@ int main(int ac, char **av)
|
|||||||
die(MBERR_INIT_ERROR);
|
die(MBERR_INIT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_telnet();
|
telnet_init();
|
||||||
|
|
||||||
tmp = calloc(81, sizeof(char ));
|
tmp = calloc(81, sizeof(char ));
|
||||||
sprintf(tmp, "mbtelnetd v%s\r\n", VERSION);
|
sprintf(tmp, "mbtelnetd v%s\r\n", VERSION);
|
||||||
write1(tmp, strlen(tmp));
|
telnet_write(tmp, strlen(tmp));
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
com_gw(s);
|
com_gw(s);
|
||||||
@ -218,139 +202,12 @@ int main(int ac, char **av)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* --- This is an artwork of serge terekhov, 2:5000/13@fidonet :) --- */
|
|
||||||
|
|
||||||
void answer (int tag, int opt)
|
|
||||||
{
|
|
||||||
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 (1, buf, 3) != 3)
|
|
||||||
WriteError("$answer cant send");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int init_telnet(void)
|
|
||||||
{
|
|
||||||
tellen = 0;
|
|
||||||
answer (DO, TN_SUPPRESS_GA);
|
|
||||||
answer (WILL, TN_SUPPRESS_GA);
|
|
||||||
answer (DO, TN_TRANSMIT_BINARY);
|
|
||||||
answer (WILL, TN_TRANSMIT_BINARY);
|
|
||||||
answer (DO, TN_ECHO);
|
|
||||||
answer (WILL, TN_ECHO);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int read0 (char *buf, int len)
|
|
||||||
{
|
|
||||||
int n = 0, m;
|
|
||||||
char *q, *p;
|
|
||||||
static char telbuf[4];
|
|
||||||
|
|
||||||
while ((n == 0) && (n = read (0, buf + tellen, MBT_BUFSIZ - tellen)) > 0) {
|
|
||||||
if (tellen) {
|
|
||||||
memcpy(buf, telbuf, tellen);
|
|
||||||
n += tellen;
|
|
||||||
tellen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memchr (buf, IAC, n)) {
|
|
||||||
for (p = q = buf; n--; )
|
|
||||||
if ((m = (unsigned char)*q++) != IAC)
|
|
||||||
*p++ = m;
|
|
||||||
else {
|
|
||||||
if (n < 2) {
|
|
||||||
memcpy (telbuf, q - 1, tellen = n + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--n;
|
|
||||||
switch (m = (unsigned char)*q++) {
|
|
||||||
case WILL: m = (unsigned char)*q++; --n;
|
|
||||||
Syslog('s', "TELNET: recv WILL %d", m);
|
|
||||||
if (m != TN_TRANSMIT_BINARY && m != TN_SUPPRESS_GA && m != TN_ECHO)
|
|
||||||
answer (DONT, m);
|
|
||||||
break;
|
|
||||||
case WONT: m = *q++;
|
|
||||||
--n;
|
|
||||||
Syslog('s', "TELNET: recv WONT %d", m);
|
|
||||||
break;
|
|
||||||
case DO: m = (unsigned char)*q++;
|
|
||||||
--n;
|
|
||||||
Syslog('s', "TELNET: recv DO %d", m);
|
|
||||||
if (m != TN_TRANSMIT_BINARY && m != TN_SUPPRESS_GA && m != TN_ECHO)
|
|
||||||
answer (WONT, m);
|
|
||||||
break;
|
|
||||||
case DONT: m = (unsigned char)*q++;
|
|
||||||
--n;
|
|
||||||
Syslog('s', "TELNET: recv DONT %d", m);
|
|
||||||
break;
|
|
||||||
case IAC: *p++ = IAC;
|
|
||||||
break;
|
|
||||||
default: Syslog('s', "TELNET: recv IAC %d", m);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n = p - buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int write1 (char *buf, int len)
|
|
||||||
{
|
|
||||||
char *q;
|
|
||||||
int k, l;
|
|
||||||
|
|
||||||
l = len;
|
|
||||||
while ((len > 0) && (q = memchr(buf, IAC, len))) {
|
|
||||||
k = (q - buf) + 1;
|
|
||||||
if ((write (1, buf, k) != k) || (write (1, q, 1) != 1)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buf += k;
|
|
||||||
len -= k;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((len > 0) && write (1, buf, len) != len) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void com_gw(int in)
|
void com_gw(int in)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int n, fdsbits;
|
int n, fdsbits;
|
||||||
static struct timeval tout = { MBT_TIMEOUT, 0 };
|
static struct timeval tout = { MBT_TIMEOUT, 0 };
|
||||||
unsigned char buf[MBT_BUFSIZ];
|
unsigned char buf[H_ZIPBUFLEN];
|
||||||
|
|
||||||
alarm(0);
|
alarm(0);
|
||||||
fdsbits = in + 1;
|
fdsbits = in + 1;
|
||||||
@ -366,7 +223,7 @@ void com_gw(int in)
|
|||||||
if ((n = select(fdsbits, &fds, NULL, NULL, &tout)) > 0) {
|
if ((n = select(fdsbits, &fds, NULL, NULL, &tout)) > 0) {
|
||||||
if (FD_ISSET(in, &fds)) {
|
if (FD_ISSET(in, &fds)) {
|
||||||
if ((n = read(in, buf, sizeof buf)) > 0) {
|
if ((n = read(in, buf, sizeof buf)) > 0) {
|
||||||
if (write1(buf, n) < 0) {
|
if (telnet_write(buf, n) < 0) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -374,7 +231,7 @@ void com_gw(int in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FD_ISSET(0, &fds)) {
|
if (FD_ISSET(0, &fds)) {
|
||||||
if ((n = read0(buf, sizeof buf)) > 0) {
|
if ((n = telnet_read(buf, sizeof buf)) > 0) {
|
||||||
if (write(in, buf, n) < 0) goto bad;
|
if (write(in, buf, n) < 0) goto bad;
|
||||||
} else {
|
} else {
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -221,42 +221,3 @@ void closetcp(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_TELNET
|
|
||||||
|
|
||||||
#define WILL 251
|
|
||||||
#define WONT 252
|
|
||||||
#define DO 253
|
|
||||||
#define DONT 254
|
|
||||||
#define IAC 255
|
|
||||||
|
|
||||||
#define TOPT_BIN 0
|
|
||||||
#define TOPT_ECHO 1
|
|
||||||
#define TOPT_SUPP 3
|
|
||||||
|
|
||||||
|
|
||||||
static void telnet_answer(int tag, int opt)
|
|
||||||
{
|
|
||||||
char buf[3];
|
|
||||||
|
|
||||||
Syslog('s', "telnet_answer(%d, %d)", tag, opt);
|
|
||||||
buf[0]=IAC;
|
|
||||||
buf[1]=tag;
|
|
||||||
buf[2]=opt;
|
|
||||||
tty_put(buf, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void telnet_init(void)
|
|
||||||
{
|
|
||||||
Syslog('s', "telnet_init()");
|
|
||||||
telnet_answer(DO,TOPT_SUPP);
|
|
||||||
telnet_answer(WILL,TOPT_SUPP);
|
|
||||||
telnet_answer(DO,TOPT_BIN);
|
|
||||||
telnet_answer(WILL,TOPT_BIN);
|
|
||||||
telnet_answer(DO,TOPT_ECHO);
|
|
||||||
telnet_answer(WILL,TOPT_ECHO);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -6,8 +6,4 @@
|
|||||||
int opentcp(char *);
|
int opentcp(char *);
|
||||||
void closetcp(void);
|
void closetcp(void);
|
||||||
|
|
||||||
#ifdef USE_TELNET
|
|
||||||
void telnet_init(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
249
mbcico/telnio.c
Normal file
249
mbcico/telnio.c
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $id$
|
||||||
|
* Purpose ...............: Telnet IO filter
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2003
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "../lib/libs.h"
|
||||||
|
#include "../lib/clcomm.h"
|
||||||
|
#include "hydra.h"
|
||||||
|
#include "telnio.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int tellen;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* --- This is an artwork of serge terekhov, 2:5000/13@fidonet :) --- */
|
||||||
|
|
||||||
|
void telnet_answer(int tag, int opt)
|
||||||
|
{
|
||||||
|
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 (1, buf, 3) != 3)
|
||||||
|
WriteError("$answer cant send");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int telnet_init(void)
|
||||||
|
{
|
||||||
|
Syslog('s', "telnet_init()");
|
||||||
|
tellen = 0;
|
||||||
|
telnet_answer(DO, TOPT_SUPP);
|
||||||
|
telnet_answer(WILL, TOPT_SUPP);
|
||||||
|
telnet_answer(DO, TOPT_BIN);
|
||||||
|
telnet_answer(WILL, TOPT_BIN);
|
||||||
|
telnet_answer(DO, TOPT_ECHO);
|
||||||
|
telnet_answer(WILL, TOPT_ECHO);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read function for mbtelnetd
|
||||||
|
*/
|
||||||
|
int telnet_read(char *buf, int len)
|
||||||
|
{
|
||||||
|
int n = 0, m;
|
||||||
|
char *q, *p;
|
||||||
|
static char telbuf[4];
|
||||||
|
|
||||||
|
Syslog('s', "telnet_read(buf, %d tellen=%d)", len, tellen);
|
||||||
|
while ((n == 0) && (n = read (0, buf + tellen, H_ZIPBUFLEN - tellen)) > 0) {
|
||||||
|
|
||||||
|
Syslog('s', " n=%d tellen=%d", n, tellen);
|
||||||
|
if (n < 0) {
|
||||||
|
Syslog('s', "telnet_read n=%d", n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tellen) {
|
||||||
|
Syslog('s', " memcpy");
|
||||||
|
memcpy(buf, telbuf, tellen);
|
||||||
|
n += tellen;
|
||||||
|
tellen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memchr (buf, IAC, n)) {
|
||||||
|
Syslog('s', " IAC detected");
|
||||||
|
for (p = q = buf; n--; )
|
||||||
|
if ((m = (unsigned char)*q++) != IAC)
|
||||||
|
*p++ = m;
|
||||||
|
else {
|
||||||
|
if (n < 2) {
|
||||||
|
memcpy (telbuf, q - 1, tellen = n + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--n;
|
||||||
|
switch (m = (unsigned char)*q++) {
|
||||||
|
case WILL: m = (unsigned char)*q++; --n;
|
||||||
|
Syslog('s', "TELNET: recv WILL %d", m);
|
||||||
|
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
|
||||||
|
telnet_answer(DONT, m);
|
||||||
|
break;
|
||||||
|
case WONT: m = *q++;
|
||||||
|
--n;
|
||||||
|
Syslog('s', "TELNET: recv WONT %d", m);
|
||||||
|
break;
|
||||||
|
case DO: m = (unsigned char)*q++;
|
||||||
|
--n;
|
||||||
|
Syslog('s', "TELNET: recv DO %d", m);
|
||||||
|
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
|
||||||
|
telnet_answer(WONT, m);
|
||||||
|
break;
|
||||||
|
case DONT: m = (unsigned char)*q++;
|
||||||
|
--n;
|
||||||
|
Syslog('s', "TELNET: recv DONT %d", m);
|
||||||
|
break;
|
||||||
|
case IAC: Syslog('s', "TELNET: recv 2nd IAC %d", m);
|
||||||
|
*p++ = IAC;
|
||||||
|
break;
|
||||||
|
default: Syslog('s', "TELNET: recv IAC %d", m);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = p - buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Syslog('s', " return n=%d", n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Telnet output filter, IAC characters are escaped.
|
||||||
|
*/
|
||||||
|
int telnet_write(char *buf, int len)
|
||||||
|
{
|
||||||
|
char *q;
|
||||||
|
int k, l;
|
||||||
|
|
||||||
|
Syslog('s', "telnet_write(buf, %d)", len);
|
||||||
|
l = len;
|
||||||
|
while ((len > 0) && (q = memchr(buf, IAC, len))) {
|
||||||
|
k = (q - buf) + 1;
|
||||||
|
if ((write(1, buf, k) != k) || (write(1, q, 1) != 1)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buf += k;
|
||||||
|
len -= k;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len > 0) && write(1, buf, len) != len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int telnet_buffer(char *buf, int len)
|
||||||
|
{
|
||||||
|
int i, j, m = 0, rc;
|
||||||
|
|
||||||
|
rc = len;
|
||||||
|
|
||||||
|
if (memchr (buf, IAC, rc)) {
|
||||||
|
Syslog('s', "telnet_buffer: IAC in input stream rc=%d", rc);
|
||||||
|
// Syslogp('s', printable(buf, rc));
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < rc; i++) {
|
||||||
|
if ((buf[i] & 0xff) == IAC) {
|
||||||
|
i++;
|
||||||
|
switch (buf[i] & 0xff) {
|
||||||
|
case WILL: i++;
|
||||||
|
m = buf[i] & 0xff;
|
||||||
|
Syslog('s', "Telnet recv WILL %d", m);
|
||||||
|
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
|
||||||
|
telnet_answer(DONT, m);
|
||||||
|
break;
|
||||||
|
case WONT: i++;
|
||||||
|
m = buf[i] & 0xff;
|
||||||
|
Syslog('s', "Telnet recv WONT %d", m);
|
||||||
|
break;
|
||||||
|
case DO: i++;
|
||||||
|
m = buf[i] & 0xff;
|
||||||
|
Syslog('s', "Telnet recv DO %d", m);
|
||||||
|
if (m != TOPT_BIN && m != TOPT_SUPP && m != TOPT_ECHO)
|
||||||
|
telnet_answer(WONT, m);
|
||||||
|
break;
|
||||||
|
case DONT: i++;
|
||||||
|
m = buf[i] & 0xff;
|
||||||
|
Syslog('s', "Telnet recv DONT %d", m);
|
||||||
|
break;
|
||||||
|
case IAC: buf[j] = buf[i];
|
||||||
|
j++;
|
||||||
|
Syslog('s', "Telnet recv escaped IAC");
|
||||||
|
break;
|
||||||
|
default: m = buf[i] & 0xff;
|
||||||
|
Syslog('s', "TELNET: recv IAC %d, this is not good", m);
|
||||||
|
buf[j] = IAC;
|
||||||
|
j++;
|
||||||
|
buf[j] = m;
|
||||||
|
j++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf[j] = buf[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = j;
|
||||||
|
// Syslog('s', "new rc=%d", rc);
|
||||||
|
// Syslogp('s', printable(buf, rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
23
mbcico/telnio.h
Normal file
23
mbcico/telnio.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _TELNIO_H
|
||||||
|
#define _TELNIO_H
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
|
||||||
|
#define MBT_WILL 251
|
||||||
|
#define MBT_WONT 252
|
||||||
|
#define MBT_DO 253
|
||||||
|
#define MBT_DONT 254
|
||||||
|
#define MBT_IAC 255
|
||||||
|
|
||||||
|
#define TOPT_BIN 0
|
||||||
|
#define TOPT_ECHO 1
|
||||||
|
#define TOPT_SUPP 3
|
||||||
|
|
||||||
|
void telnet_answer(int, int);
|
||||||
|
int telnet_init(void);
|
||||||
|
int telnet_read(char *, int);
|
||||||
|
int telnet_write(char *, int);
|
||||||
|
int telnet_buffer(char *, int);
|
||||||
|
|
||||||
|
#endif
|
206
mbcico/ttyio.c
206
mbcico/ttyio.c
@ -38,14 +38,17 @@
|
|||||||
#include "../lib/records.h"
|
#include "../lib/records.h"
|
||||||
#include "../lib/common.h"
|
#include "../lib/common.h"
|
||||||
#include "../lib/clcomm.h"
|
#include "../lib/clcomm.h"
|
||||||
|
#include "telnio.h"
|
||||||
#include "ttyio.h"
|
#include "ttyio.h"
|
||||||
#include "lutil.h"
|
#include "lutil.h"
|
||||||
|
|
||||||
extern int hanged_up;
|
extern int hanged_up;
|
||||||
|
extern int telnet;
|
||||||
|
extern int master;
|
||||||
extern char *inetaddr;
|
extern char *inetaddr;
|
||||||
|
|
||||||
#define TT_BUFSIZ 1024
|
#define TT_BUFSIZ 1024
|
||||||
#define NUMTIMERS 3
|
#define NUMTIMERS 3
|
||||||
|
|
||||||
|
|
||||||
int tty_status = 0;
|
int tty_status = 0;
|
||||||
@ -241,6 +244,10 @@ static int tty_read(char *buf, int size, int tot)
|
|||||||
Syslog('!', "tty_read: error flag");
|
Syslog('!', "tty_read: error flag");
|
||||||
}
|
}
|
||||||
rc=-tty_status;
|
rc=-tty_status;
|
||||||
|
} else {
|
||||||
|
if (master && telnet) {
|
||||||
|
rc = telnet_buffer(buf, rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -253,7 +260,10 @@ int tty_write(char *buf, int size)
|
|||||||
int result;
|
int result;
|
||||||
|
|
||||||
tty_status=0;
|
tty_status=0;
|
||||||
result = write(1,buf,size);
|
if (telnet && master)
|
||||||
|
result = telnet_write(buf, size);
|
||||||
|
else
|
||||||
|
result = write(1, buf, size);
|
||||||
|
|
||||||
if (result != size) {
|
if (result != size) {
|
||||||
if (hanged_up || (errno == EPIPE) || (errno == ECONNRESET)) {
|
if (hanged_up || (errno == EPIPE) || (errno == ECONNRESET)) {
|
||||||
@ -461,135 +471,141 @@ int tty_getc(int tot)
|
|||||||
|
|
||||||
int tty_get(char *buf, int size, int tot)
|
int tty_get(char *buf, int size, int tot)
|
||||||
{
|
{
|
||||||
int result=0;
|
int result=0;
|
||||||
|
|
||||||
if (left >= size) {
|
if (left >= size) {
|
||||||
memcpy(buf,next,size);
|
memcpy(buf,next,size);
|
||||||
next += size;
|
next += size;
|
||||||
left -= size;
|
left -= size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left > 0) {
|
if (left > 0) {
|
||||||
memcpy(buf,next,left);
|
memcpy(buf,next,left);
|
||||||
buf += left;
|
buf += left;
|
||||||
next += left;
|
next += left;
|
||||||
size -= left;
|
size -= left;
|
||||||
left=0;
|
left=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((result=tty_read(buf,size,tot)) > 0) {
|
while ((result=tty_read(buf,size,tot)) > 0) {
|
||||||
buf += result;
|
buf += result;
|
||||||
size -= result;
|
size -= result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int tty_putc(int c)
|
int tty_putc(int c)
|
||||||
{
|
{
|
||||||
char buf = c;
|
char buf = c;
|
||||||
|
|
||||||
return tty_write(&buf,1);
|
return tty_write(&buf,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int tty_put(char *buf, int size)
|
int tty_put(char *buf, int size)
|
||||||
{
|
{
|
||||||
return tty_write(buf,size);
|
return tty_write(buf,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int tty_putget(char **obuf, int *osize, char **ibuf, int *isize)
|
int tty_putget(char **obuf, int *osize, char **ibuf, int *isize)
|
||||||
{
|
{
|
||||||
time_t timeout, now;
|
time_t timeout, now;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
fd_set readfds, writefds, exceptfds;
|
fd_set readfds, writefds, exceptfds;
|
||||||
struct timeval seltimer;
|
struct timeval seltimer;
|
||||||
|
|
||||||
tty_status = 0;
|
tty_status = 0;
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
timeout = (time_t)300; /* maximum of 5 minutes */
|
timeout = (time_t)300; /* maximum of 5 minutes */
|
||||||
|
|
||||||
for (i = 0; i < NUMTIMERS; i++) {
|
for (i = 0; i < NUMTIMERS; i++) {
|
||||||
if (timer[i]) {
|
if (timer[i]) {
|
||||||
if (now >= timer[i]) {
|
if (now >= timer[i]) {
|
||||||
tty_status = STAT_TIMEOUT;
|
tty_status = STAT_TIMEOUT;
|
||||||
WriteError("tty_putget: timer %d already expired, return",i);
|
WriteError("tty_putget: timer %d already expired, return",i);
|
||||||
return -tty_status;
|
return -tty_status;
|
||||||
} else {
|
} else {
|
||||||
if (timeout > (timer[i]-now))
|
if (timeout > (timer[i]-now))
|
||||||
timeout=timer[i]-now;
|
timeout=timer[i]-now;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Syslog('t', "tty_putget: timeout=%d",timeout);
|
Syslog('t', "tty_putget: timeout=%d",timeout);
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
FD_ZERO(&writefds);
|
FD_ZERO(&writefds);
|
||||||
FD_ZERO(&exceptfds);
|
FD_ZERO(&exceptfds);
|
||||||
FD_SET(0,&readfds);
|
FD_SET(0,&readfds);
|
||||||
FD_SET(1,&writefds);
|
FD_SET(1,&writefds);
|
||||||
FD_SET(0,&exceptfds);
|
FD_SET(0,&exceptfds);
|
||||||
FD_SET(1,&exceptfds);
|
FD_SET(1,&exceptfds);
|
||||||
seltimer.tv_sec=timeout;
|
seltimer.tv_sec=timeout;
|
||||||
seltimer.tv_usec=0;
|
seltimer.tv_usec=0;
|
||||||
|
|
||||||
rc=select(2,&readfds,&writefds,&exceptfds,&seltimer);
|
rc=select(2,&readfds,&writefds,&exceptfds,&seltimer);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if (hanged_up) {
|
if (hanged_up) {
|
||||||
tty_status=STAT_HANGUP;
|
tty_status=STAT_HANGUP;
|
||||||
WriteError("tty_putget: hanged_up flag");
|
WriteError("tty_putget: hanged_up flag");
|
||||||
} else {
|
|
||||||
WriteError("$tty_putget: select failed");
|
|
||||||
tty_status=STAT_ERROR;
|
|
||||||
}
|
|
||||||
} else if (rc == 0) {
|
|
||||||
tty_status=STAT_TIMEOUT;
|
|
||||||
} else {
|
} else {
|
||||||
/* rc > 0 */
|
WriteError("$tty_putget: select failed");
|
||||||
if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) {
|
tty_status=STAT_ERROR;
|
||||||
WriteError("$tty_putget: exeption error");
|
|
||||||
tty_status=STAT_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if (rc == 0) {
|
||||||
if (tty_status) {
|
tty_status=STAT_TIMEOUT;
|
||||||
Syslog('t', "tty_putget: return after select status %s",ttystat[tty_status]);
|
} else {
|
||||||
return -tty_status;
|
/* rc > 0 */
|
||||||
|
if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) {
|
||||||
|
WriteError("$tty_putget: exeption error");
|
||||||
|
tty_status=STAT_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FD_ISSET(0,&readfds) && *isize) {
|
if (tty_status) {
|
||||||
rc=read(0,*ibuf,*isize);
|
Syslog('t', "tty_putget: return after select status %s",ttystat[tty_status]);
|
||||||
if (rc < 0) {
|
return -tty_status;
|
||||||
WriteError("$tty_putget: read failed");
|
}
|
||||||
tty_status=STAT_ERROR;
|
|
||||||
} else {
|
if (FD_ISSET(0,&readfds) && *isize) {
|
||||||
(*ibuf)+=rc;
|
rc = read(0, *ibuf, *isize);
|
||||||
(*isize)-=rc;
|
if (rc < 0) {
|
||||||
}
|
WriteError("$tty_putget: read failed");
|
||||||
|
tty_status=STAT_ERROR;
|
||||||
|
} else {
|
||||||
|
if (master && telnet) {
|
||||||
|
rc = telnet_buffer(*ibuf, rc);
|
||||||
|
}
|
||||||
|
(*ibuf)+=rc;
|
||||||
|
(*isize)-=rc;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FD_ISSET(1,&writefds) && *osize) {
|
if (FD_ISSET(1,&writefds) && *osize) {
|
||||||
rc=write(1,*obuf,*osize);
|
if (telnet && master)
|
||||||
if (rc < 0) {
|
rc = telnet_write(*obuf,*osize);
|
||||||
WriteError("$tty_putget: write failed");
|
else
|
||||||
tty_status=STAT_ERROR;
|
rc=write(1,*obuf,*osize);
|
||||||
} else {
|
if (rc < 0) {
|
||||||
(*obuf)+=rc;
|
WriteError("$tty_putget: write failed");
|
||||||
(*osize)-=rc;
|
tty_status=STAT_ERROR;
|
||||||
}
|
} else {
|
||||||
|
(*obuf)+=rc;
|
||||||
|
(*osize)-=rc;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tty_status)
|
if (tty_status)
|
||||||
return -tty_status;
|
return -tty_status;
|
||||||
else
|
else
|
||||||
return ((*isize == 0) | ((*osize == 0) << 1));
|
return ((*isize == 0) | ((*osize == 0) << 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user