summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-08 00:02:40 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-08 00:02:40 +0800
commit657d43f453ffa4360d8716c49006bdd3297f86b4 (patch)
treef5ca28e0e15fba073d2dd65d1ea2cc73f8b26220
parent5c8bb43b13925613c4c35b7483c421cc1abe62a0 (diff)
downloadpttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar.gz
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar.bz2
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar.lz
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar.xz
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.tar.zst
pttbbs-657d43f453ffa4360d8716c49006bdd3297f86b4.zip
* add client code detection to tunnel mode
* refine telnet library to support write customization git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4517 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--common/sys/telnet.c79
-rw-r--r--include/cmsys.h17
-rw-r--r--include/logind.h4
-rw-r--r--mbbsd/mbbsd.c6
-rw-r--r--mbbsd/telnet.c3
5 files changed, 78 insertions, 31 deletions
diff --git a/common/sys/telnet.c b/common/sys/telnet.c
index 2f462867..ddb3de07 100644
--- a/common/sys/telnet.c
+++ b/common/sys/telnet.c
@@ -1,6 +1,9 @@
/*
* piaip's simplified implementation of TELNET protocol
+ * Copyright (c) 2005-2009 Hung-Te Lin <piaip@csie.ntu.edu.tw>
+ * Improved by Kuang 2009
*/
+
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -15,6 +18,7 @@
#include "cmsys.h"
static unsigned int telnet_handler(TelnetCtx *ctx, unsigned char c) ;
+static void telnet_write (TelnetCtx *ctx, const void *buf, size_t nbytes);
enum TELNET_IAC_STATES {
IAC_NONE,
@@ -25,7 +29,6 @@ enum TELNET_IAC_STATES {
IAC_ERROR
};
-
/* We don't reply to most commands, so this maxlen can be minimal.
* Warning: if you want to support ENV passing or other long commands,
* remember to increase this value. Howver, some poorly implemented
@@ -38,10 +41,17 @@ TelnetCtx *telnet_create_contex(void)
return (TelnetCtx*) malloc(sizeof(TelnetCtx));
}
+void telnet_free_context(TelnetCtx* ctx)
+{
+ free(ctx);
+}
+
void telnet_ctx_init(TelnetCtx *ctx, const struct TelnetCallback *callback, int fd)
{
memset(ctx, 0, sizeof(TelnetCtx));
+ // callback structure must be provided.
+ assert(callback);
ctx->callback = callback;
ctx->fd = fd;
}
@@ -51,6 +61,16 @@ void telnet_ctx_set_cc_arg(TelnetCtx *ctx, void *cc_arg)
ctx->cc_arg = cc_arg;
}
+void telnet_ctx_set_write_arg(TelnetCtx *ctx, void *write_arg)
+{
+ ctx->write_arg = write_arg;
+}
+
+void telnet_ctx_set_resize_arg(TelnetCtx *ctx, void *resize_arg)
+{
+ ctx->resize_arg = resize_arg;
+}
+
/* We are the boss. We don't respect to client.
* It's client's responsibility to follow us.
* Please write these codes in i-dont-care opt handlers.
@@ -74,9 +94,9 @@ static const char telnet_init_cmds[] = {
IAC, DO, TELOPT_BINARY,
};
-void telnet_send_init_cmds(int fd)
+void telnet_ctx_send_init_cmds(TelnetCtx *ctx)
{
- write(fd, telnet_init_cmds, sizeof(telnet_init_cmds));
+ telnet_write(ctx, telnet_init_cmds, sizeof(telnet_init_cmds));
}
ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size)
@@ -106,6 +126,15 @@ ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size)
extern unsigned char fakeEscape;
#endif // DBG_OUTRPT
+static void
+telnet_write (TelnetCtx *ctx, const void *buf, size_t nbytes)
+{
+ if (ctx->callback->write_data)
+ ctx->callback->write_data(ctx->write_arg, ctx->fd, buf, nbytes);
+ else
+ write(ctx->fd, buf, nbytes);
+}
+
/* input: raw character
* output: telnet command if c was handled, otherwise zero.
*/
@@ -150,10 +179,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
#if 0 // def DEBUG
{
int cx = c; /* to make compiler happy */
- write(ctx->fd, "-", 1);
+ telnet_write(ctx, "-", 1);
if(TELCMD_OK(cx))
- write(ctx->fd, TELCMD(c), strlen(TELCMD(c)));
- write(ctx->fd, " ", 1);
+ telnet_write(ctx, TELCMD(c), strlen(TELCMD(c)));
+ telnet_write(ctx, " ", 1);
}
#endif
ctx->iac_state = IAC_NONE; /* by default we restore state. */
@@ -192,18 +221,18 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
case AYT: /* are you there */
{
#if 0
- const char *alive = "I'm still alive, loading: ";
- char buf[STRLEN];
-
- /* respond as fast as we can */
- write(ctx->fd, alive, strlen(alive));
- cpuload(buf);
- write(ctx->fd, buf, strlen(buf));
- write(ctx->fd, "\r\n", 2);
+ const char *alive = " I'm still alive, loading: ";
+ char buf[STRLEN];
+
+ /* respond as fast as we can */
+ telnet_write(ctx, alive, strlen(alive));
+ cpuload(buf);
+ telnet_write(ctx, buf, strlen(buf));
+ telnet_write(ctx, "\r\n", 2);
#else
- const char *alive = "I'm still alive\r\n";
- /* respond as fast as we can */
- write(ctx->fd, alive, strlen(alive));
+ const char *alive = " I'm still alive.\r\n";
+ /* respond as fast as we can */
+ telnet_write(ctx, alive, strlen(alive));
#endif
}
return NOP;
@@ -229,10 +258,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
case IAC_WAIT_OPT:
#if 0 // def DEBUG
- write(ctx->fd, "-", 1);
+ telnet_write(ctx, "-", 1);
if(TELOPT_OK(c))
- write(ctx->fd, TELOPT(c), strlen(TELOPT(c)));
- write(ctx->fd, " ", 1);
+ telnet_write(ctx, TELOPT(c), strlen(TELOPT(c)));
+ telnet_write(ctx, " ", 1);
#endif
ctx->iac_state = IAC_NONE;
/*
@@ -245,7 +274,7 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
*/
switch(c) {
/* i-dont-care: i don't care about what client is.
- * these should be clamed in init and
+ * these should be claimed in init and
* client must follow me. */
case TELOPT_TTYPE: /* termtype or line. */
case TELOPT_NAWS: /* resize terminal */
@@ -265,7 +294,7 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
unsigned char cmd[3] = { IAC, DONT, 0 };
if(ctx->iac_opt_req == DO) cmd[1] = WONT;
cmd[2] = c;
- write(ctx->fd, cmd, sizeof(cmd));
+ telnet_write(ctx, cmd, sizeof(cmd));
}
break;
}
@@ -288,10 +317,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c)
case IAC_PROCESS_OPT:
ctx->iac_state = IAC_NONE;
#if 0 // def DEBUG
- write(ctx->fd, "-", 1);
+ telnet_write(ctx, "-", 1);
if(TELOPT_OK(ctx->iac_buf[0]))
- write(ctx->fd, TELOPT(ctx->iac_buf[0]), strlen(TELOPT(ctx->iac_buf[0])));
- write(ctx->fd, " ", 1);
+ telnet_write(ctx, TELOPT(ctx->iac_buf[0]), strlen(TELOPT(ctx->iac_buf[0])));
+ telnet_write(ctx, " ", 1);
#endif
switch(ctx->iac_buf[0]) {
diff --git a/include/cmsys.h b/include/cmsys.h
index 863aab3f..6ae2119f 100644
--- a/include/cmsys.h
+++ b/include/cmsys.h
@@ -178,6 +178,7 @@ extern int Vector_search(const struct Vector *self, const char *name);
/* telnet.c */
struct TelnetCallback {
+ void (*write_data) (void *write_arg, int fd, const void *buf, size_t nbytes);
void (*term_resize) (void *resize_arg, int w, int h);
void (*update_client_code) (void *cc_arg, unsigned char seq);
};
@@ -197,16 +198,22 @@ struct TelnetCtx {
const struct TelnetCallback *callback;
// callback parameters
+ void *write_arg; // write_data
void *resize_arg; // term_resize
void *cc_arg; // update_client_code
};
typedef struct TelnetCtx TelnetCtx;
-extern TelnetCtx *telnet_create_contex(void);
-extern void telnet_ctx_init(TelnetCtx *ctx, const struct TelnetCallback *callback, int fd);
-extern void telnet_ctx_set_cc_arg(TelnetCtx *ctx, void *cc_arg);
+extern TelnetCtx *telnet_create_context(void);
+extern void telnet_free_context (TelnetCtx *ctx);
-extern void telnet_send_init_cmds(int fd);
-extern ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size);
+extern void telnet_ctx_init (TelnetCtx *ctx, const struct TelnetCallback *callback, int fd);
+extern void telnet_ctx_send_init_cmds(TelnetCtx *ctx);
+
+extern void telnet_ctx_set_cc_arg (TelnetCtx *ctx, void *cc_arg);
+extern void telnet_ctx_set_write_arg (TelnetCtx *ctx, void *cc_arg);
+extern void telnet_ctx_set_resize_arg(TelnetCtx *ctx, void *cc_arg);
+
+extern ssize_t telnet_process (TelnetCtx *ctx, unsigned char *buf, ssize_t size);
#endif
diff --git a/include/logind.h b/include/logind.h
index 0b229faa..493d0c09 100644
--- a/include/logind.h
+++ b/include/logind.h
@@ -7,9 +7,13 @@
typedef struct login_data
{
+ // size of current structure
+ size_t cb;
+
// terminal information
int t_lines, t_cols;
int encoding;
+ Fnv32_t client_code;
// user authentication
char userid[IDLEN+1];
diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c
index ff9188d8..6d86247b 100644
--- a/mbbsd/mbbsd.c
+++ b/mbbsd/mbbsd.c
@@ -1853,6 +1853,8 @@ tunnel_login(char *argv0, struct ProgramOption *option)
towrite(tunnel, &success, sizeof(success)) < sizeof(success))
return 0;
+ assert(dat.cb == sizeof(dat));
+
// optimize connection
set_connection_opt(csock);
@@ -1880,6 +1882,10 @@ tunnel_login(char *argv0, struct ProgramOption *option)
option->term_width = dat.t_cols;
option->term_height = dat.t_lines;
telnet_init(0);
+#ifdef DETECT_CLIENT
+ telnet_turnoff_client_detect();
+ client_code = dat.client_code; // use the client code detected by remote daemon
+#endif
return 1;
}
diff --git a/mbbsd/telnet.c b/mbbsd/telnet.c
index d60254ac..7cf1fee5 100644
--- a/mbbsd/telnet.c
+++ b/mbbsd/telnet.c
@@ -20,6 +20,7 @@ telnet_cb_resize_term(void *resize_arg, int w, int h)
}
const static struct TelnetCallback telnet_callback = {
+ NULL,
telnet_cb_resize_term,
#ifdef DETECT_CLIENT
telnet_cb_update_client_code,
@@ -39,7 +40,7 @@ telnet_init(int do_init_cmd)
telnet_ctx_set_cc_arg(ctx, (void*)1);
#endif
if (do_init_cmd)
- telnet_send_init_cmds(fd);
+ telnet_ctx_send_init_cmds(ctx);
}
/* tty_read