Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50a6b600bf | |||
| 465f31ba87 | |||
| 90c5387613 | |||
| 6bf10a6901 | |||
| f759c0e3cc | |||
| 0606891b78 | |||
| 899596fd5b | |||
| a21ba0cb9c | |||
| 8f03384964 | |||
| b314659125 | |||
| 42a4e2e062 | |||
| 0b402cdb6b | |||
| 302ed6d796 | |||
| bf11b1dd15 | |||
| 33de2e875c | |||
| eccd32fdfb | |||
| 089b733f27 | |||
| 41802ce7e9 | |||
| e51a98e4b2 | |||
| 9db6c5d83c | |||
| e3675b9e89 |
+1
-1
@@ -20,7 +20,7 @@ Makefile
|
|||||||
|
|
||||||
# build
|
# build
|
||||||
*.o
|
*.o
|
||||||
/ttynvt
|
/src/ttynvt
|
||||||
|
|
||||||
/ttynvt-*.tar.gz
|
/ttynvt-*.tar.gz
|
||||||
/ttynvt-*.tar.xz
|
/ttynvt-*.tar.xz
|
||||||
|
|||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
-kr -i4 --no-tabs --line-length79 -di16
|
||||||
|
--braces-after-if-line --brace-indent0 --dont-cuddle-else --cuddle-do-while
|
||||||
|
--blank-lines-after-declarations --blank-lines-after-procedures
|
||||||
|
--break-after-boolean-operator
|
||||||
|
--no-space-after-casts
|
||||||
|
--else-endif-column0
|
||||||
+2
-15
@@ -1,20 +1,7 @@
|
|||||||
# Build ttynvt
|
|
||||||
#
|
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
aclocal.m4 autom4te.cache compile config.h.in config.h.in~ configure \
|
aclocal.m4 autom4te.cache compile config.h.in config.h.in~ configure \
|
||||||
depcomp install-sh missing \
|
depcomp install-sh missing \
|
||||||
Makefile.in
|
Makefile.in */Makefile.in
|
||||||
|
|
||||||
CFLAGS_OPT = -O3
|
SUBDIRS = src
|
||||||
CFLAGS_WARN = -Wall -Wextra -Werror -Wno-unused-parameter
|
|
||||||
|
|
||||||
bin_PROGRAMS = ttynvt
|
|
||||||
|
|
||||||
ttynvt_SOURCES = \
|
|
||||||
ttynvt.c \
|
|
||||||
telnet_basic.c telnet_rfc2217.c telnet.h telnet_param.h
|
|
||||||
|
|
||||||
ttynvt_CPPFLAGS = -I$(top_builddir) $(FUSE_CFLAGS) $(CFLAGS_OPT) $(CFLAGS_WARN)
|
|
||||||
|
|
||||||
ttynvt_LDADD = $(FUSE_LIBS)
|
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
m4_define([pkg_version], [0.14])
|
m4_define([pkg_version], [0.15])
|
||||||
#m4_define([pkg_revision], [005])
|
#m4_define([pkg_revision], [005])
|
||||||
m4_define([pkg_version], m4_ifdef([pkg_revision], [pkg_version.pkg_revision], [pkg_version]))
|
m4_define([pkg_version], m4_ifdef([pkg_revision], [pkg_version.pkg_revision], [pkg_version]))
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ PKG_CHECK_MODULES(FUSE, fuse)
|
|||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
|
src/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
CFLAGS_WARN = -Wall -Wextra -Werror -Wno-unused-parameter
|
||||||
|
|
||||||
|
bin_PROGRAMS = ttynvt
|
||||||
|
|
||||||
|
ttynvt_SOURCES = \
|
||||||
|
ttynvt.c nvt_log.c nvt_log.h \
|
||||||
|
telnet_basic.c telnet_rfc2217.c telnet.h telnet_param.h
|
||||||
|
|
||||||
|
ttynvt_CPPFLAGS = -I$(top_builddir) $(FUSE_CFLAGS) $(CFLAGS_WARN)
|
||||||
|
|
||||||
|
ttynvt_LDADD = $(FUSE_LIBS)
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Logging functions
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "nvt_log.h"
|
||||||
|
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#define gettid() (pid_t)syscall(__NR_gettid)
|
||||||
|
|
||||||
|
char log_level = 0;
|
||||||
|
char log_stdout = 0;
|
||||||
|
|
||||||
|
static const char *_hms_txt(char *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
unsigned int sod, hh, mm, ss;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
sod = tv.tv_sec % (24 * 3600);
|
||||||
|
hh = sod / 3600;
|
||||||
|
mm = (sod - hh * 3600) / 60;
|
||||||
|
ss = sod - hh * 3600 - mm * 60;
|
||||||
|
snprintf(buf, len, "%02d:%02d:%02d.%06d",
|
||||||
|
hh, mm, ss, (unsigned int)tv.tv_usec);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvt_log(int prio, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
char buf[256], buft[64];
|
||||||
|
const char *eol;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof(buf), fmt, arg);
|
||||||
|
|
||||||
|
if (log_stdout)
|
||||||
|
{
|
||||||
|
eol = (len > 0 && buf[len - 1] != '\n') ? "\n" : "";
|
||||||
|
printf("%s: [%d] %d: %s%s",
|
||||||
|
_hms_txt(buft, sizeof(buft)), gettid(), prio, buf, eol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syslog(prio, "[%d] %s", gettid(), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BPL 16 /* Bytes per line */
|
||||||
|
|
||||||
|
void nvt_log_buf(int prio, const char *txt, const void *ptr_, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int ix, i, imax;
|
||||||
|
int l, n;
|
||||||
|
char buf[128];
|
||||||
|
const unsigned char *ptr = ptr_;
|
||||||
|
|
||||||
|
for (ix = 0; ix < len || (len == 0 && ix == 0); ix += BPL)
|
||||||
|
{
|
||||||
|
n = snprintf(buf, sizeof(buf), "%s: %04x:", txt, ix);
|
||||||
|
if (n <= 0)
|
||||||
|
return; /* Just playing it safe */
|
||||||
|
imax = (len - ix < BPL) ? len - ix : BPL;
|
||||||
|
for (i = 0; i < imax; i++)
|
||||||
|
{
|
||||||
|
l = snprintf(buf + n, sizeof(buf) - n, " %02x", *ptr++);
|
||||||
|
if (l <= 0)
|
||||||
|
return; /* Just playing it safe */
|
||||||
|
n += l;
|
||||||
|
}
|
||||||
|
nvt_log(prio, "%s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Logging functions
|
||||||
|
*/
|
||||||
|
#ifndef NVT_LOG_H
|
||||||
|
#define NVT_LOG_H
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#define _PRF_N_(no) __attribute__((__format__(__printf__, (no), (no) + 1)))
|
||||||
|
#define _PRF2_ _PRF_N_(2)
|
||||||
|
|
||||||
|
_PRF2_ void nvt_log(int prio, const char *fmt, ...);
|
||||||
|
void nvt_log_buf(int prio, const char *txt,
|
||||||
|
const void *ptr, unsigned int len);
|
||||||
|
|
||||||
|
extern char log_level;
|
||||||
|
extern char log_stdout;
|
||||||
|
|
||||||
|
#define DBG(...) \
|
||||||
|
if (log_level > 0) nvt_log(LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#define DBG2(...) \
|
||||||
|
if (log_level > 1) nvt_log(LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#define DBG2_BUF(txt, ptr, len) \
|
||||||
|
if (log_level > 1) nvt_log_buf(LOG_DEBUG, txt, ptr, len)
|
||||||
|
|
||||||
|
#endif /* NVT_LOG_H */
|
||||||
@@ -60,11 +60,12 @@ extern void telnet_rfc2217_ctl(tn_ctx_t * tcc, unsigned int val);
|
|||||||
|
|
||||||
/*RFC2217 control commands*/
|
/*RFC2217 control commands*/
|
||||||
#define TNS_CTL_NOFLOW 1
|
#define TNS_CTL_NOFLOW 1
|
||||||
#define TNS_CTL_XONOFF 2
|
#define TNS_CTL_XONOFF_OUT 2
|
||||||
#define TNS_CTL_CTSRTS 3
|
#define TNS_CTL_CTSRTS 3
|
||||||
#define TNS_CTL_DTR_ON 8
|
#define TNS_CTL_DTR_ON 8
|
||||||
#define TNS_CTL_DTR_OFF 9
|
#define TNS_CTL_DTR_OFF 9
|
||||||
#define TNS_CTL_RTS_ON 11
|
#define TNS_CTL_RTS_ON 11
|
||||||
#define TNS_CTL_RTS_OFF 12
|
#define TNS_CTL_RTS_OFF 12
|
||||||
|
#define TNS_CTL_XONOFF_IN 15
|
||||||
|
|
||||||
#endif /*TELNET_H */
|
#endif /*TELNET_H */
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Lars Thrane A/S
|
||||||
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Telnet parameters
|
||||||
|
*/
|
||||||
|
#ifndef TELNET_PARAM_H
|
||||||
|
#define TELNET_PARAM_H
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Telnet commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TNC_F0_SE (0xf0) /* End of subnegotiation parameters */
|
||||||
|
#define TNC_F1_NOP (0xf1) /* No operation */
|
||||||
|
#define TNC_F2_MARK (0xf2) /* The data stream portion of a Synch.
|
||||||
|
This should always be accompanied
|
||||||
|
by a TCP Urgent notification. */
|
||||||
|
#define TNC_F3_BRK (0xf3) /* NVT character BRK. */
|
||||||
|
#define TNC_F4_IP (0xf4) /* The function IP (interrupt process) */
|
||||||
|
#define TNC_F5_AO (0xf5) /* The function AO (abort output) */
|
||||||
|
#define TNC_F6_AYT (0xf6) /* The function AYT (are you there) */
|
||||||
|
#define TNC_F7_EC (0xf7) /* The function EC (erase charceter) */
|
||||||
|
#define TNC_F8_EL (0xf8) /* The function EL (erase line) */
|
||||||
|
#define TNC_F9_GA (0xf9) /* The GA signal (go ahead) */
|
||||||
|
#define TNC_FA_SB (0xfa) /* Subnegotiation begin */
|
||||||
|
#define TNC_FB_WILL (0xfb) /* Indicates the desire to begin
|
||||||
|
performing, or confirmation that
|
||||||
|
you are now performing, the
|
||||||
|
indicated option. */
|
||||||
|
#define TNC_FC_WONT (0xfc) /* Indicates the refusal to perform,
|
||||||
|
or continue performing, the
|
||||||
|
indicated option. */
|
||||||
|
#define TNC_FD_DO (0xfd) /* Indicates the request that the
|
||||||
|
other party perform, or
|
||||||
|
confirmation that you are expecting
|
||||||
|
the other party to perform, the
|
||||||
|
indicated option. */
|
||||||
|
#define TNC_FE_DONT (0xfe) /* Indicates the demand that the
|
||||||
|
other party stop performing,
|
||||||
|
or confirmation that you are no
|
||||||
|
longer expecting the other party
|
||||||
|
to perform, the indicated option. */
|
||||||
|
#define TNC_FF_IAC (0xff) /* Interpret as Command / data byte */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Telnet options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* https://www.iana.org/assignments/telnet-options/telnet-options.xhtml
|
||||||
|
*
|
||||||
|
* 0 00 Binary Transmission [RFC856]
|
||||||
|
* 1 01 Echo [RFC857]
|
||||||
|
* 2 02 Reconnection [DDN Protocol Handbook, ... ]
|
||||||
|
* 3 03 Suppress Go Ahead [RFC858]
|
||||||
|
* 4 04 Approx Message Size Negotiation ["The Ethernet, ..." ]
|
||||||
|
* 5 05 Status [RFC859]
|
||||||
|
* 6 06 Timing Mark [RFC860]
|
||||||
|
* 7 07 Remote Controlled Trans and Echo [RFC726]
|
||||||
|
* 8 08 Output Line Width [DDN Protocol Handbook, ... ]
|
||||||
|
* 9 09 Output Page Size [DDN Protocol Handbook, ... ]
|
||||||
|
* 10 0a Output Carriage-Return Disposition [RFC652]
|
||||||
|
* 11 0b Output Horizontal Tab Stops [RFC653]
|
||||||
|
* 12 0c Output Horizontal Tab Disposition [RFC654]
|
||||||
|
* 13 0d Output Formfeed Disposition [RFC655]
|
||||||
|
* 14 0e Output Vertical Tabstops [RFC656]
|
||||||
|
* 15 0f Output Vertical Tab Disposition [RFC657]
|
||||||
|
* 16 10 Output Linefeed Disposition [RFC658]
|
||||||
|
* 17 11 Extended ASCII [RFC698]
|
||||||
|
* 18 12 Logout [RFC727]
|
||||||
|
* 19 13 Byte Macro [RFC735]
|
||||||
|
* 20 14 Data Entry Terminal [RFC1043][RFC732]
|
||||||
|
* 21 15 SUPDUP [RFC736][RFC734]
|
||||||
|
* 22 16 SUPDUP Output [RFC749]
|
||||||
|
* 23 17 Send Location [RFC779]
|
||||||
|
* 24 18 Terminal Type [RFC1091]
|
||||||
|
* 25 19 End of Record [RFC885]
|
||||||
|
* 26 1a TACACS User Identification [RFC927]
|
||||||
|
* 27 1b Output Marking [RFC933]
|
||||||
|
* 28 1c Terminal Location Number [RFC946]
|
||||||
|
* 29 1d Telnet 3270 Regime [RFC1041]
|
||||||
|
* 30 1e X.3 PAD [RFC1053]
|
||||||
|
* 31 1f Negotiate About Window Size [RFC1073]
|
||||||
|
* 32 20 Terminal Speed [RFC1079]
|
||||||
|
* 33 21 Remote Flow Control [RFC1372]
|
||||||
|
* 34 22 Linemode [RFC1184]
|
||||||
|
* 35 23 X Display Location [RFC1096]
|
||||||
|
* 36 24 Environment Option [RFC1408]
|
||||||
|
* 37 25 Authentication Option [RFC2941]
|
||||||
|
* 38 26 Encryption Option [RFC2946]
|
||||||
|
* 39 27 New Environment Option [RFC1572]
|
||||||
|
* 40 28 TN3270E [RFC2355]
|
||||||
|
* 41 29 XAUTH [Rob_Earhart]
|
||||||
|
* 42 2a CHARSET [RFC2066]
|
||||||
|
* 43 2b Telnet Remote Serial Port (RSP) [Robert_Barnes]
|
||||||
|
* 44 2c Com Port Control Option [RFC2217]
|
||||||
|
* 45 2d Telnet Suppress Local Echo [Wirt_Atmar]
|
||||||
|
* 46 2e Telnet Start TLS [Michael_Boe]
|
||||||
|
* 47 2f KERMIT [RFC2840]
|
||||||
|
* 48 30 SEND-URL [David_Croft]
|
||||||
|
* 49 31 FORWARD_X [Jeffrey_Altman]
|
||||||
|
* 50-137 32-89 Unassigned [IANA]
|
||||||
|
* 138 8a TELOPT PRAGMA LOGON [Steve_McGregory]
|
||||||
|
* 139 8b TELOPT SSPI LOGON [Steve_McGregory]
|
||||||
|
* 140 8c TELOPT PRAGMA HEARTBEAT [Steve_McGregory]
|
||||||
|
* 141-254 8d-fe Unassigned
|
||||||
|
* 255 ff Extended-Options-List [RFC861]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TNO_BINARY 0 /* 00 Binary Transmission */
|
||||||
|
#define TNO_ECHO 1 /* 01 Echo */
|
||||||
|
#define TNO_SUPP_GA 3 /* 03 Suppress Go Ahead */
|
||||||
|
#define TNO_LOGOUT 18 /* 12 Logout */
|
||||||
|
#define TNO_TTYP 24 /* 18 Terminal Type */
|
||||||
|
#define TNO_NAWS 31 /* 1f Negotiate About Window Size */
|
||||||
|
#define TNO_NEO 39 /* 27 New Environment Option */
|
||||||
|
#define TNO_CPCO 44 /* 2c RFC 2217 */
|
||||||
|
#define TNO_KERMIT 47 /* 2f Kermit */
|
||||||
|
|
||||||
|
#endif /* TELNET_PARAM_H */
|
||||||
+130
-117
@@ -8,8 +8,10 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fuse_opt.h>
|
#include <fuse_opt.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -17,16 +19,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <asm/ioctls.h>
|
||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <linux/ppp-ioctl.h>
|
#include <linux/ppp-ioctl.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
|
#include "nvt_log.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
|
|
||||||
#define NET_BUF_SIZE 1024
|
#define NET_BUF_SIZE 1024
|
||||||
@@ -36,9 +37,6 @@
|
|||||||
#define FD_MASTER 1
|
#define FD_MASTER 1
|
||||||
#define FD_SLAVE 2
|
#define FD_SLAVE 2
|
||||||
|
|
||||||
#define _PRF_N_(no) __attribute__((__format__(__printf__, (no), (no) + 1)))
|
|
||||||
#define _PRF2_ _PRF_N_(2)
|
|
||||||
|
|
||||||
|
|
||||||
static struct ttynvt_param {
|
static struct ttynvt_param {
|
||||||
unsigned int major;
|
unsigned int major;
|
||||||
@@ -70,7 +68,7 @@ typedef struct {
|
|||||||
char net_buf[NET_BUF_SIZE];
|
char net_buf[NET_BUF_SIZE];
|
||||||
int net_cnt;
|
int net_cnt;
|
||||||
|
|
||||||
struct termios tio;
|
struct termios2 tio;
|
||||||
|
|
||||||
int cmcr; /* Commanded by ioctl */
|
int cmcr; /* Commanded by ioctl */
|
||||||
volatile int smcr; /* Status from modem */
|
volatile int smcr; /* Status from modem */
|
||||||
@@ -84,80 +82,6 @@ typedef struct {
|
|||||||
tn_ctx_t *tn;
|
tn_ctx_t *tn;
|
||||||
} ttynvt_t;
|
} ttynvt_t;
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#define gettid() (pid_t)syscall(__NR_gettid)
|
|
||||||
|
|
||||||
static const char *_hms_txt(char *buf, unsigned int len)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
unsigned int sod, hh, mm, ss;
|
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
|
|
||||||
sod = tv.tv_sec % (24 * 3600);
|
|
||||||
hh = sod / 3600;
|
|
||||||
mm = (sod - hh * 3600) / 60;
|
|
||||||
ss = sod - hh * 3600 - mm * 60;
|
|
||||||
snprintf(buf, len, "%02d:%02d:%02d.%06d",
|
|
||||||
hh, mm, ss, (unsigned int)tv.tv_usec);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
_PRF2_ static void _log(int prio, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list arg;
|
|
||||||
char buf[256], buft[64];
|
|
||||||
|
|
||||||
va_start(arg, fmt);
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, arg);
|
|
||||||
|
|
||||||
if (ttynvt_param.logstd)
|
|
||||||
{
|
|
||||||
printf("%s: [%d] %d: %s",
|
|
||||||
_hms_txt(buft, sizeof(buft)), gettid(), prio, buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
syslog(prio, "[%d] %s", gettid(), buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BPL 16 /* Bytes per line */
|
|
||||||
|
|
||||||
void _log_buf(int prio, const char *txt, const void *ptr_, unsigned int len)
|
|
||||||
{
|
|
||||||
unsigned int ix, i, imax;
|
|
||||||
int l, n;
|
|
||||||
char buf[128];
|
|
||||||
const unsigned char *ptr = ptr_;
|
|
||||||
|
|
||||||
for (ix = 0; ix < len || (len == 0 && ix == 0); ix += BPL)
|
|
||||||
{
|
|
||||||
n = snprintf(buf, sizeof(buf), "%s: %04x:", txt, ix);
|
|
||||||
if (n <= 0)
|
|
||||||
return; /* Just playing it safe */
|
|
||||||
imax = (len - ix < BPL) ? len - ix : BPL;
|
|
||||||
for (i = 0; i < imax; i++)
|
|
||||||
{
|
|
||||||
l = snprintf(buf + n, sizeof(buf) - n, " %02x", *ptr++);
|
|
||||||
if (l <= 0)
|
|
||||||
return; /* Just playing it safe */
|
|
||||||
n += l;
|
|
||||||
}
|
|
||||||
_log(prio, "%s\n", buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DBG(...) \
|
|
||||||
if (ttynvt_param.debug > 0) _log(LOG_DEBUG, __VA_ARGS__)
|
|
||||||
#define DBG2(...) \
|
|
||||||
if (ttynvt_param.debug > 1) _log(LOG_DEBUG, __VA_ARGS__)
|
|
||||||
#define DBG2_BUF(txt, ptr, len) \
|
|
||||||
if (ttynvt_param.debug > 1) _log_buf(LOG_DEBUG, txt, ptr, len)
|
|
||||||
|
|
||||||
static void _fd_close(int fd)
|
static void _fd_close(int fd)
|
||||||
{
|
{
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
@@ -213,7 +137,7 @@ static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
||||||
|
|
||||||
_log(LOG_INFO, "connection closed\n");
|
nvt_log(LOG_INFO, "connection closed\n");
|
||||||
|
|
||||||
tty->rel_pending = 1;
|
tty->rel_pending = 1;
|
||||||
_fd_close(tty->fds[FD_NET].fd);
|
_fd_close(tty->fds[FD_NET].fd);
|
||||||
@@ -309,12 +233,12 @@ static void *_read_net(void *arg)
|
|||||||
NET_BUF_SIZE - tty->net_cnt);
|
NET_BUF_SIZE - tty->net_cnt);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "net read error: %m\n");
|
nvt_log(LOG_ERR, "net read error: %m\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
_log(LOG_INFO, "Connection closed by remote host\n");
|
nvt_log(LOG_INFO, "Connection closed by remote host\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tty->net_cnt += res;
|
tty->net_cnt += res;
|
||||||
@@ -328,7 +252,7 @@ static void *_read_net(void *arg)
|
|||||||
write(tty->fds[FD_MASTER].fd, tty->net_buf, tty->net_cnt);
|
write(tty->fds[FD_MASTER].fd, tty->net_buf, tty->net_cnt);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "master write error: %m\n");
|
nvt_log(LOG_ERR, "master write error: %m\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tty->net_cnt = 0;
|
tty->net_cnt = 0;
|
||||||
@@ -343,7 +267,7 @@ static void *_read_net(void *arg)
|
|||||||
DBG("%s: read res=%d pollout=%d\n", __func__, res, tty->pollout);
|
DBG("%s: read res=%d pollout=%d\n", __func__, res, tty->pollout);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "master read error: %m\n");
|
nvt_log(LOG_ERR, "master read error: %m\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tty->pollout == 0)
|
if (tty->pollout == 0)
|
||||||
@@ -382,14 +306,14 @@ static int _srv_connect(const char *host, unsigned int port)
|
|||||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sockfd < 0)
|
if (sockfd < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "Socket open failed: %m\n");
|
nvt_log(LOG_ERR, "Socket open failed: %m\n");
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
server = gethostbyname(host);
|
server = gethostbyname(host);
|
||||||
if (server == NULL)
|
if (server == NULL)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "Cannot resolve host name: %m\n");
|
nvt_log(LOG_ERR, "Cannot resolve host name: %m\n");
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -403,7 +327,7 @@ static int _srv_connect(const char *host, unsigned int port)
|
|||||||
err = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
|
err = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "Failed to connect to: %s:%u: %m\n", host, port);
|
nvt_log(LOG_ERR, "Failed to connect to: %s:%u: %m\n", host, port);
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -478,6 +402,7 @@ static void _modem_status_cb(void *cctx, int status)
|
|||||||
if (status & TNS_STATE_CTS)
|
if (status & TNS_STATE_CTS)
|
||||||
mcr |= TIOCM_CTS;
|
mcr |= TIOCM_CTS;
|
||||||
|
|
||||||
|
if (tty->tio.c_cflag & CRTSCTS)
|
||||||
tty->master_suspended = (mcr & TIOCM_CTS) ? 0 : 1;
|
tty->master_suspended = (mcr & TIOCM_CTS) ? 0 : 1;
|
||||||
DBG("%s: tty=%p mcr=%x MS=%d\n", __func__, tty, mcr,
|
DBG("%s: tty=%p mcr=%x MS=%d\n", __func__, tty, mcr,
|
||||||
tty->master_suspended);
|
tty->master_suspended);
|
||||||
@@ -588,7 +513,7 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
info->nonseekable = 1;
|
info->nonseekable = 1;
|
||||||
info->direct_io = 1;
|
info->direct_io = 1;
|
||||||
|
|
||||||
_log(LOG_INFO, "Connected to server: %s:%d\n",
|
nvt_log(LOG_INFO, "Connected to server: %s:%d\n",
|
||||||
ttynvt_param.host, ttynvt_param.port);
|
ttynvt_param.host, ttynvt_param.port);
|
||||||
|
|
||||||
fuse_reply_open(req, info);
|
fuse_reply_open(req, info);
|
||||||
@@ -597,7 +522,7 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
|
|
||||||
open_err:
|
open_err:
|
||||||
|
|
||||||
_log(LOG_INFO, "Connection to server: %s:%d failed: %m\n",
|
nvt_log(LOG_INFO, "Connection to server: %s:%d failed: %m\n",
|
||||||
ttynvt_param.host, ttynvt_param.port);
|
ttynvt_param.host, ttynvt_param.port);
|
||||||
|
|
||||||
for (n = 0; n < 3; n++)
|
for (n = 0; n < 3; n++)
|
||||||
@@ -623,7 +548,7 @@ ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
|||||||
DBG2("%s: tty->error=%d\n", __func__, tty->error);
|
DBG2("%s: tty->error=%d\n", __func__, tty->error);
|
||||||
if (tty->epipe == 0)
|
if (tty->epipe == 0)
|
||||||
{
|
{
|
||||||
_log(LOG_WARNING, "Rx EPIPE\n");
|
nvt_log(LOG_WARNING, "Rx EPIPE\n");
|
||||||
tty->epipe = 1;
|
tty->epipe = 1;
|
||||||
fuse_reply_buf(req, NULL, 0);
|
fuse_reply_buf(req, NULL, 0);
|
||||||
}
|
}
|
||||||
@@ -699,6 +624,7 @@ ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
|||||||
}
|
}
|
||||||
else if (res != (int)size)
|
else if (res != (int)size)
|
||||||
{
|
{
|
||||||
|
DBG("%s: caution: tty->pollout set to 0\n", __func__);
|
||||||
tty->pollout = 0;
|
tty->pollout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,9 +633,13 @@ ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
|||||||
|
|
||||||
static int baudrate(speed_t speed)
|
static int baudrate(speed_t speed)
|
||||||
{
|
{
|
||||||
|
/**INDENT-OFF**/
|
||||||
return speed == B50 ? 50 :
|
return speed == B50 ? 50 :
|
||||||
speed == B75 ? 75 :
|
speed == B75 ? 75 :
|
||||||
speed == B110 ? 110 :
|
speed == B110 ? 110 :
|
||||||
|
speed == B134 ? 134 :
|
||||||
|
speed == B150 ? 150 :
|
||||||
|
speed == B200 ? 200 :
|
||||||
speed == B300 ? 300 :
|
speed == B300 ? 300 :
|
||||||
speed == B600 ? 600 :
|
speed == B600 ? 600 :
|
||||||
speed == B1200 ? 1200 :
|
speed == B1200 ? 1200 :
|
||||||
@@ -720,7 +650,21 @@ static int baudrate(speed_t speed)
|
|||||||
speed == B19200 ? 19200 :
|
speed == B19200 ? 19200 :
|
||||||
speed == B38400 ? 38400 :
|
speed == B38400 ? 38400 :
|
||||||
speed == B57600 ? 57600 :
|
speed == B57600 ? 57600 :
|
||||||
speed == B115200 ? 115200 : speed == B230400 ? 230400 : 0;
|
speed == B115200 ? 115200 :
|
||||||
|
speed == B230400 ? 230400 :
|
||||||
|
speed == B460800 ? 460800 :
|
||||||
|
speed == B500000 ? 500000 :
|
||||||
|
speed == B576000 ? 576000 :
|
||||||
|
speed == B921600 ? 921600 :
|
||||||
|
speed == B1000000 ? 1000000 :
|
||||||
|
speed == B1152000 ? 1152000 :
|
||||||
|
speed == B1500000 ? 1500000 :
|
||||||
|
speed == B2000000 ? 2000000 :
|
||||||
|
speed == B2500000 ? 2500000 :
|
||||||
|
speed == B3000000 ? 3000000 :
|
||||||
|
speed == B3500000 ? 3500000 :
|
||||||
|
speed == B4000000 ? 4000000 : 0;
|
||||||
|
/**INDENT-ON**/
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char pstr[] = { ' ', 'N', 'O', 'E', 'M', 'S' };
|
static const char pstr[] = { ' ', 'N', 'O', 'E', 'M', 'S' };
|
||||||
@@ -737,9 +681,13 @@ static const char *_ioctl_name(int cmd)
|
|||||||
snprintf(buf, sizeof(buf), "0x%x", cmd);
|
snprintf(buf, sizeof(buf), "0x%x", cmd);
|
||||||
return buf;
|
return buf;
|
||||||
CASE(TCSETSF);
|
CASE(TCSETSF);
|
||||||
|
CASE(TCSETSF2);
|
||||||
CASE(TCSETSW);
|
CASE(TCSETSW);
|
||||||
|
CASE(TCSETSW2);
|
||||||
CASE(TCSETS);
|
CASE(TCSETS);
|
||||||
|
CASE(TCSETS2);
|
||||||
CASE(TCGETS);
|
CASE(TCGETS);
|
||||||
|
CASE(TCGETS2);
|
||||||
CASE(TIOCINQ);
|
CASE(TIOCINQ);
|
||||||
CASE(TIOCOUTQ);
|
CASE(TIOCOUTQ);
|
||||||
CASE(TCFLSH);
|
CASE(TCFLSH);
|
||||||
@@ -765,7 +713,7 @@ static const char *_ioctl_name(int cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int _tio_parity(const struct termios *tio)
|
static unsigned int _tio_parity(const struct termios2 *tio)
|
||||||
{
|
{
|
||||||
unsigned int par;
|
unsigned int par;
|
||||||
|
|
||||||
@@ -788,12 +736,20 @@ static unsigned int _tio_parity(const struct termios *tio)
|
|||||||
return par;
|
return par;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int _tio_baud(const struct termios *tio)
|
static unsigned int _tio_baud(const struct termios2 *tio)
|
||||||
{
|
{
|
||||||
return baudrate(tio->c_cflag & (CBAUD | CBAUDEX));
|
return baudrate(tio->c_cflag & (CBAUD | CBAUDEX));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int _tio_csize(const struct termios *tio)
|
static unsigned int _tio2_baud(const struct termios2 *tio2)
|
||||||
|
{
|
||||||
|
if ((tio2->c_cflag & CBAUD) == BOTHER)
|
||||||
|
return tio2->c_ospeed;
|
||||||
|
|
||||||
|
return _tio_baud(tio2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int _tio_csize(const struct termios2 *tio)
|
||||||
{
|
{
|
||||||
unsigned int csize;
|
unsigned int csize;
|
||||||
|
|
||||||
@@ -809,7 +765,7 @@ static unsigned int _tio_csize(const struct termios *tio)
|
|||||||
return csize;
|
return csize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int _tio_stopb(const struct termios *tio)
|
static unsigned int _tio_stopb(const struct termios2 *tio)
|
||||||
{
|
{
|
||||||
unsigned int stopb;
|
unsigned int stopb;
|
||||||
|
|
||||||
@@ -821,7 +777,7 @@ static unsigned int _tio_stopb(const struct termios *tio)
|
|||||||
return stopb;
|
return stopb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _show_termios(const char *txt, const struct termios *tio)
|
static void _show_termios(const char *txt, const struct termios2 *tio)
|
||||||
{
|
{
|
||||||
DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt,
|
DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt,
|
||||||
_tio_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio),
|
_tio_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio),
|
||||||
@@ -830,6 +786,16 @@ static void _show_termios(const char *txt, const struct termios *tio)
|
|||||||
tio->c_cflag & HUPCL ? '+' : '-', tio->c_cflag & CLOCAL ? '+' : '-');
|
tio->c_cflag & HUPCL ? '+' : '-', tio->c_cflag & CLOCAL ? '+' : '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _show_termios2(const char *txt, const struct termios2 *tio)
|
||||||
|
{
|
||||||
|
DBG("%s: %u%c%u%u %cCTSRTS %cCREAD %cHUPCL %cCLOCAL\n", txt,
|
||||||
|
_tio2_baud(tio), pstr[_tio_parity(tio)], _tio_csize(tio),
|
||||||
|
_tio_stopb(tio),
|
||||||
|
tio->c_cflag & CRTSCTS ? '+' : '-', tio->c_cflag & CREAD ? '+' : '-',
|
||||||
|
tio->c_cflag & HUPCL ? '+' : '-', tio->c_cflag & CLOCAL ? '+' : '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define CHECK_BUF_IN(sz) \
|
#define CHECK_BUF_IN(sz) \
|
||||||
if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0)
|
if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0)
|
||||||
#define CHECK_BUF_OUT(sz) \
|
#define CHECK_BUF_OUT(sz) \
|
||||||
@@ -841,14 +807,14 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
||||||
struct termios *tio = &tty->tio;
|
struct termios2 *tio = &tty->tio;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
unsigned int tiocm = 0;
|
unsigned int tiocm, baud;
|
||||||
int mcr;
|
int mcr;
|
||||||
int val;
|
int val;
|
||||||
int res;
|
int res;
|
||||||
unsigned char byte;
|
uint8_t byte;
|
||||||
unsigned int byte4;
|
uint32_t byte4;
|
||||||
|
|
||||||
DBG("%s: cmd=%s arg=%p ibuf=%p:%u obuf=:%u\n", __func__,
|
DBG("%s: cmd=%s arg=%p ibuf=%p:%u obuf=:%u\n", __func__,
|
||||||
_ioctl_name(cmd), arg, in_buf,
|
_ioctl_name(cmd), arg, in_buf,
|
||||||
@@ -860,10 +826,19 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
case TCSETSW:
|
case TCSETSW:
|
||||||
case TCSETS:
|
case TCSETS:
|
||||||
CHECK_BUF_IN(sizeof(struct termios));
|
CHECK_BUF_IN(sizeof(struct termios));
|
||||||
{
|
|
||||||
memcpy(tio, in_buf, in_bufsz);
|
memcpy(tio, in_buf, in_bufsz);
|
||||||
|
baud = _tio_baud(tio);
|
||||||
byte4 = htonl(_tio_baud(tio));
|
goto do_tcset;
|
||||||
|
case TCSETSF2:
|
||||||
|
case TCSETSW2:
|
||||||
|
case TCSETS2:
|
||||||
|
CHECK_BUF_IN(sizeof(struct termios2));
|
||||||
|
memcpy(tio, in_buf, in_bufsz);
|
||||||
|
baud = _tio2_baud(tio);
|
||||||
|
goto do_tcset;
|
||||||
|
do_tcset:
|
||||||
|
/* BEWARE of termios/termios2 buf structure difference! */
|
||||||
|
byte4 = htonl(baud);
|
||||||
telnet_rfc2217_cfg(tty->tn, TNS_SET_BAUDRATE, &byte4, 4);
|
telnet_rfc2217_cfg(tty->tn, TNS_SET_BAUDRATE, &byte4, 4);
|
||||||
|
|
||||||
byte = _tio_csize(tio);
|
byte = _tio_csize(tio);
|
||||||
@@ -877,24 +852,48 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
|
|
||||||
if (tio->c_cflag & CRTSCTS)
|
if (tio->c_cflag & CRTSCTS)
|
||||||
{
|
{
|
||||||
tty->cmcr |= TIOCM_RTS;
|
tty->master_suspended = (tty->smcr & TIOCM_CTS) ? 0 : 1;
|
||||||
telnet_rfc2217_ctl(tty->tn, TNS_CTL_CTSRTS);
|
telnet_rfc2217_ctl(tty->tn, TNS_CTL_CTSRTS);
|
||||||
}
|
}
|
||||||
|
else if (tio->c_iflag & (IXON | IXOFF))
|
||||||
|
{
|
||||||
|
tty->master_suspended = 0;
|
||||||
|
if (tio->c_iflag & IXON)
|
||||||
|
telnet_rfc2217_ctl(tty->tn, TNS_CTL_XONOFF_OUT);
|
||||||
|
if (tio->c_iflag & IXOFF)
|
||||||
|
telnet_rfc2217_ctl(tty->tn, TNS_CTL_XONOFF_IN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tty->master_suspended = 0;
|
||||||
|
telnet_rfc2217_ctl(tty->tn, TNS_CTL_NOFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(tty->cmcr & TIOCM_DTR) && _tio_baud(tio) != 0)
|
if (!(tty->cmcr & TIOCM_DTR) && baud != 0)
|
||||||
{
|
{
|
||||||
tty->cmcr |= TIOCM_DTR;
|
tty->cmcr |= TIOCM_DTR;
|
||||||
telnet_rfc2217_ctl(tty->tn, TNS_CTL_DTR_ON);
|
telnet_rfc2217_ctl(tty->tn, TNS_CTL_DTR_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case TCSETSF:
|
||||||
|
case TCSETSW:
|
||||||
|
case TCSETS:
|
||||||
_show_termios("TCSETS", tio);
|
_show_termios("TCSETS", tio);
|
||||||
|
break;
|
||||||
|
case TCSETSF2:
|
||||||
|
case TCSETSW2:
|
||||||
|
case TCSETS2:
|
||||||
|
_show_termios2("TCSETS2", tio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ioctl(tty->fds[FD_SLAVE].fd, cmd, tio);
|
ioctl(tty->fds[FD_SLAVE].fd, cmd, tio);
|
||||||
|
|
||||||
if (cmd == TCSETSF)
|
if (cmd == TCSETSF || cmd == TCSETSF2)
|
||||||
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TCGETS:
|
case TCGETS:
|
||||||
CHECK_BUF_OUT(sizeof(struct termios));
|
CHECK_BUF_OUT(sizeof(struct termios));
|
||||||
@@ -902,6 +901,12 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
_show_termios("TCGETS", tio);
|
_show_termios("TCGETS", tio);
|
||||||
fuse_reply_ioctl(req, 0, tio, sizeof(struct termios));
|
fuse_reply_ioctl(req, 0, tio, sizeof(struct termios));
|
||||||
break;
|
break;
|
||||||
|
case TCGETS2:
|
||||||
|
CHECK_BUF_OUT(sizeof(struct termios2));
|
||||||
|
ioctl(tty->fds[FD_SLAVE].fd, TCGETS2, tio);
|
||||||
|
_show_termios2("TCGETS2", tio);
|
||||||
|
fuse_reply_ioctl(req, 0, tio, sizeof(struct termios2));
|
||||||
|
break;
|
||||||
case TIOCINQ: /* Get the number of bytes in the input
|
case TIOCINQ: /* Get the number of bytes in the input
|
||||||
* buffer */
|
* buffer */
|
||||||
CHECK_BUF_OUT(sizeof(int));
|
CHECK_BUF_OUT(sizeof(int));
|
||||||
@@ -915,12 +920,13 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
||||||
break;
|
break;
|
||||||
case TCFLSH:
|
case TCFLSH:
|
||||||
switch ((size_t) arg)
|
switch ((size_t)arg)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case TCIFLUSH:
|
case TCIFLUSH:
|
||||||
byte = 1;
|
byte = 1;
|
||||||
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
|
tty->pollin = 0;
|
||||||
break;
|
break;
|
||||||
case TCOFLUSH:
|
case TCOFLUSH:
|
||||||
byte = 2;
|
byte = 2;
|
||||||
@@ -930,6 +936,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
byte = 3;
|
byte = 3;
|
||||||
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
tty->pollout = 1;
|
tty->pollout = 1;
|
||||||
|
tty->pollin = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
telnet_rfc2217_cfg(tty->tn, TNS_SET_PURGE, &byte, 1);
|
telnet_rfc2217_cfg(tty->tn, TNS_SET_PURGE, &byte, 1);
|
||||||
@@ -945,7 +952,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
break;
|
break;
|
||||||
case TIOCMBIS:
|
case TIOCMBIS:
|
||||||
CHECK_BUF_IN(sizeof(int));
|
CHECK_BUF_IN(sizeof(int));
|
||||||
tiocm = *(unsigned int *)in_buf;
|
tiocm = *(const unsigned int *)in_buf;
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
||||||
if (tiocm & TIOCM_RTS)
|
if (tiocm & TIOCM_RTS)
|
||||||
@@ -961,7 +968,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
goto show_mctl;
|
goto show_mctl;
|
||||||
case TIOCMBIC:
|
case TIOCMBIC:
|
||||||
CHECK_BUF_IN(sizeof(int));
|
CHECK_BUF_IN(sizeof(int));
|
||||||
tiocm = *(unsigned int *)in_buf;
|
tiocm = *(const unsigned int *)in_buf;
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
||||||
if (tiocm & TIOCM_RTS)
|
if (tiocm & TIOCM_RTS)
|
||||||
@@ -977,7 +984,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
goto show_mctl;
|
goto show_mctl;
|
||||||
case TIOCMSET:
|
case TIOCMSET:
|
||||||
CHECK_BUF_IN(sizeof(int));
|
CHECK_BUF_IN(sizeof(int));
|
||||||
tiocm = *(unsigned int *)in_buf;
|
tiocm = *(const unsigned int *)in_buf;
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
DBG("%s: cmd=%s tiocm=%#x\n", __func__, _ioctl_name(cmd), tiocm);
|
||||||
tty->cmcr &= ~(TIOCM_RTS | TIOCM_DTR);
|
tty->cmcr &= ~(TIOCM_RTS | TIOCM_DTR);
|
||||||
@@ -1007,7 +1014,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
break;
|
break;
|
||||||
case TIOCSWINSZ:
|
case TIOCSWINSZ:
|
||||||
CHECK_BUF_IN(sizeof(struct winsize));
|
CHECK_BUF_IN(sizeof(struct winsize));
|
||||||
ws = *(struct winsize *)in_buf;
|
ws = *(const struct winsize *)in_buf;
|
||||||
res = ioctl(tty->fds[FD_SLAVE].fd, TIOCSWINSZ, &ws);
|
res = ioctl(tty->fds[FD_SLAVE].fd, TIOCSWINSZ, &ws);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
@@ -1031,7 +1038,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
break;
|
break;
|
||||||
case TIOCSETD:
|
case TIOCSETD:
|
||||||
CHECK_BUF_IN(sizeof(int));
|
CHECK_BUF_IN(sizeof(int));
|
||||||
val = *(int *)in_buf;
|
val = *(const int *)in_buf;
|
||||||
res = ioctl(tty->fds[FD_SLAVE].fd, TIOCSETD, &val);
|
res = ioctl(tty->fds[FD_SLAVE].fd, TIOCSETD, &val);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
@@ -1055,6 +1062,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
DBG("ERROR: Unsupported IOCTL\n");
|
||||||
fuse_reply_err(req, ENOSYS);
|
fuse_reply_err(req, ENOSYS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1139,6 +1147,8 @@ static void print_help(void)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "ttynvt Usage:\n"
|
fprintf(stderr, "ttynvt Usage:\n"
|
||||||
"\t-D level\tEnable debug\n"
|
"\t-D level\tEnable debug\n"
|
||||||
|
"\t-d\t\tStay in foreground, do not detach\n"
|
||||||
|
"\t-f\t\tStay in foreground, do not detach\n"
|
||||||
"\t-E\t\tPrint debug to stdout (default is syslog)\n"
|
"\t-E\t\tPrint debug to stdout (default is syslog)\n"
|
||||||
"\t-M major, --maj=major\n"
|
"\t-M major, --maj=major\n"
|
||||||
"\t-m minor, --min=minor\n"
|
"\t-m minor, --min=minor\n"
|
||||||
@@ -1179,6 +1189,9 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_level = ttynvt_param.debug;
|
||||||
|
log_stdout = ttynvt_param.logstd;
|
||||||
|
|
||||||
if (!ttynvt_param.dev_name)
|
if (!ttynvt_param.dev_name)
|
||||||
ttynvt_param.dev_name = "ttyNVT0";
|
ttynvt_param.dev_name = "ttyNVT0";
|
||||||
|
|
||||||
@@ -1221,14 +1234,14 @@ int main(int argc, char *argv[])
|
|||||||
switch (cpid)
|
switch (cpid)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
_log(LOG_ERR, "fork(): %m\n");
|
nvt_log(LOG_ERR, "fork(): %m\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
case 0: /* Child */
|
case 0: /* Child */
|
||||||
DBG("Child proceeding...\n");
|
DBG("Child proceeding...\n");
|
||||||
rc = cuse_lowlevel_main(args.argc, args.argv, &ci, &ttynvt_op, NULL);
|
rc = cuse_lowlevel_main(args.argc, args.argv, &ci, &ttynvt_op, NULL);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
_log(LOG_ERR, "ttynvt failed rc=%d\n", rc);
|
nvt_log(LOG_ERR, "ttynvt failed rc=%d\n", rc);
|
||||||
else
|
else
|
||||||
DBG("Child exited\n");
|
DBG("Child exited\n");
|
||||||
return rc;
|
return rc;
|
||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 Lars Thrane A/S
|
|
||||||
* SPDX-License-Identifier: GPL-2.0
|
|
||||||
*
|
|
||||||
* Telnet parameters
|
|
||||||
*/
|
|
||||||
#ifndef TELNET_PARAM_H
|
|
||||||
#define TELNET_PARAM_H
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Telnet commands
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TNC_F0_SE (0xf0) /* End of subnegotiation parameters */
|
|
||||||
#define TNC_F1_NOP (0xf1) /* No operation */
|
|
||||||
#define TNC_F2_MARK (0xf2) /* The data stream portion of a Synch.
|
|
||||||
This should always be accompanied
|
|
||||||
by a TCP Urgent notification. */
|
|
||||||
#define TNC_F3_BRK (0xf3) /* NVT character BRK. */
|
|
||||||
#define TNC_F4_IP (0xf4) /* The function IP (interrupt process) */
|
|
||||||
#define TNC_F5_AO (0xf5) /* The function AO (abort output) */
|
|
||||||
#define TNC_F6_AYT (0xf6) /* The function AYT (are you there) */
|
|
||||||
#define TNC_F7_EC (0xf7) /* The function EC (erase charceter) */
|
|
||||||
#define TNC_F8_EL (0xf8) /* The function EL (erase line) */
|
|
||||||
#define TNC_F9_GA (0xf9) /* The GA signal (go ahead) */
|
|
||||||
#define TNC_FA_SB (0xfa) /* Subnegotiation begin */
|
|
||||||
#define TNC_FB_WILL (0xfb) /* Indicates the desire to begin
|
|
||||||
performing, or confirmation that
|
|
||||||
you are now performing, the
|
|
||||||
indicated option. */
|
|
||||||
#define TNC_FC_WONT (0xfc) /* Indicates the refusal to perform,
|
|
||||||
or continue performing, the
|
|
||||||
indicated option. */
|
|
||||||
#define TNC_FD_DO (0xfd) /* Indicates the request that the
|
|
||||||
other party perform, or
|
|
||||||
confirmation that you are expecting
|
|
||||||
the other party to perform, the
|
|
||||||
indicated option. */
|
|
||||||
#define TNC_FE_DONT (0xfe) /* Indicates the demand that the
|
|
||||||
other party stop performing,
|
|
||||||
or confirmation that you are no
|
|
||||||
longer expecting the other party
|
|
||||||
to perform, the indicated option. */
|
|
||||||
#define TNC_FF_IAC (0xff) /* Interpret as Command / data byte */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Telnet options
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* https://www.iana.org/assignments/telnet-options/telnet-options.xhtml
|
|
||||||
*
|
|
||||||
* 0 Binary Transmission [RFC856]
|
|
||||||
* 1 Echo [RFC857]
|
|
||||||
* 2 Reconnection [DDN Protocol Handbook, ... ]
|
|
||||||
* 3 Suppress Go Ahead [RFC858]
|
|
||||||
* 4 Approx Message Size Negotiation ["The Ethernet, ... ]
|
|
||||||
* 5 Status [RFC859]
|
|
||||||
* 6 Timing Mark [RFC860]
|
|
||||||
* 7 Remote Controlled Trans and Echo [RFC726]
|
|
||||||
* 8 Output Line Width [DDN Protocol Handbook, ... ]
|
|
||||||
* 9 Output Page Size [DDN Protocol Handbook, ... ]
|
|
||||||
* 10 Output Carriage-Return Disposition [RFC652]
|
|
||||||
* 11 Output Horizontal Tab Stops [RFC653]
|
|
||||||
* 12 Output Horizontal Tab Disposition [RFC654]
|
|
||||||
* 13 Output Formfeed Disposition [RFC655]
|
|
||||||
* 14 Output Vertical Tabstops [RFC656]
|
|
||||||
* 15 Output Vertical Tab Disposition [RFC657]
|
|
||||||
* 16 Output Linefeed Disposition [RFC658]
|
|
||||||
* 17 Extended ASCII [RFC698]
|
|
||||||
* 18 Logout [RFC727]
|
|
||||||
* 19 Byte Macro [RFC735]
|
|
||||||
* 20 Data Entry Terminal [RFC1043][RFC732]
|
|
||||||
* 21 SUPDUP [RFC736][RFC734]
|
|
||||||
* 22 SUPDUP Output [RFC749]
|
|
||||||
* 23 Send Location [RFC779]
|
|
||||||
* 24 Terminal Type [RFC1091]
|
|
||||||
* 25 End of Record [RFC885]
|
|
||||||
* 26 TACACS User Identification [RFC927]
|
|
||||||
* 27 Output Marking [RFC933]
|
|
||||||
* 28 Terminal Location Number [RFC946]
|
|
||||||
* 29 Telnet 3270 Regime [RFC1041]
|
|
||||||
* 30 X.3 PAD [RFC1053]
|
|
||||||
* 31 Negotiate About Window Size [RFC1073]
|
|
||||||
* 32 Terminal Speed [RFC1079]
|
|
||||||
* 33 Remote Flow Control [RFC1372]
|
|
||||||
* 34 Linemode [RFC1184]
|
|
||||||
* 35 X Display Location [RFC1096]
|
|
||||||
* 36 Environment Option [RFC1408]
|
|
||||||
* 37 Authentication Option [RFC2941]
|
|
||||||
* 38 Encryption Option [RFC2946]
|
|
||||||
* 39 New Environment Option [RFC1572]
|
|
||||||
* 40 TN3270E [RFC2355]
|
|
||||||
* 41 XAUTH [Rob_Earhart]
|
|
||||||
* 42 CHARSET [RFC2066]
|
|
||||||
* 43 Telnet Remote Serial Port (RSP) [Robert_Barnes]
|
|
||||||
* 44 Com Port Control Option [RFC2217]
|
|
||||||
* 45 Telnet Suppress Local Echo [Wirt_Atmar]
|
|
||||||
* 46 Telnet Start TLS [Michael_Boe]
|
|
||||||
* 47 KERMIT [RFC2840]
|
|
||||||
* 48 SEND-URL [David_Croft]
|
|
||||||
* 49 FORWARD_X [Jeffrey_Altman]
|
|
||||||
* 50-137 Unassigned [IANA]
|
|
||||||
* 138 TELOPT PRAGMA LOGON [Steve_McGregory]
|
|
||||||
* 139 TELOPT SSPI LOGON [Steve_McGregory]
|
|
||||||
* 140 TELOPT PRAGMA HEARTBEAT [Steve_McGregory]
|
|
||||||
* 141-254 Unassigned
|
|
||||||
* 255 Extended-Options-List [RFC861]
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TNO_BINARY 0 /* Binary Transmission */
|
|
||||||
#define TNO_ECHO 1 /* Echo */
|
|
||||||
#define TNO_SUPP_GA 3 /* Suppress Go Ahead */
|
|
||||||
#define TNO_LOGOUT 18 /* Logout */
|
|
||||||
#define TNO_TTYP 24 /* Terminal Type */
|
|
||||||
#define TNO_NAWS 31 /* Negotiate About Window Size */
|
|
||||||
#define TNO_NEO 39 /* New Environment Option */
|
|
||||||
#define TNO_CPCO 44 /* RFC 2217 */
|
|
||||||
#define TNO_KERMIT 47 /* Kermit */
|
|
||||||
|
|
||||||
#endif /* TELNET_PARAM_H */
|
|
||||||
Reference in New Issue
Block a user