Good day time!
Using openssh with a serial attached terminal figures with a problem
with flow control when serial terminal has printer connected to it etc.
because ssh disables xon/xoff on associated terminal. At present ssh
client always disables xon/xoff on associated terminal device, regarding
of it's previous state, e.g. ixon and ixoff options were set or not.
By searching the google i've found some posts where people complained
about sshing somewhere and getting disabled xon/xoff on their devices
and thus they had to use rlogin because it handles local flow control
correctly for them. An easy and quick/dirty method was to remove IXON &
IXOFF flags from sshtty.c:enter_raw_mode(), but it can easily brake
transparency. Another standart method to use was a must.
According to IETF RFC4254 ssh server can provide client an idea of doing
the control flow at the client side. A special SSH_MSG_CHANNEL_REQUEST
message with "xon-xoff" string MUST be used, and client MAY ignore this
message. This feature is not implemented in OpenSSH, nor in client nor
in the server.
As we have a great need in using software flow control on the local side
with ssh connection to server, i have decided to implement these options
in ssh server and client. The patch must be applied to the openssh 4.5p1
release.
The patch adds two boolean options in ssh and sshd correspondingly
"IgnoreFlowControl" and "UseFlowControl". Defaults don't change the
usual behaviour of neither ssh and sshd.
When "IgnoreLocalFlow" is set to "no" within ssh client, it handles
"xon-xoff" message from sshd and enables or disables local flow control
ONLY if it was previously set before ssh was started and associated with
terminal device. If no ixon or ixoff option was set on terminal device
everything is left as is.
When UseLocalFlow is set to "yes" within sshd server, it requests to
enable "xon-xoff" after the client's request of pty allocation succeeds.
Now we can use printers attached to serial terminals and other devices.
In spite of the reason, that patch works well for me, i suppose it might
be better but i need developers advice.
Best wishes,
Grigoriy A. Sitkarev
--- openssh-4.5p1/clientloop.c.orig 2006-10-23 17:02:41 +0000
+++ openssh-4.5p1/clientloop.c 2006-12-09 22:00:41 +0000
@@ -1823,7 +1823,7 @@
client_input_channel_req(int type, u_int32_t seq, void *ctxt)
{
Channel *c = NULL;
- int exitval, id, reply, success = 0;
+ int exitval, lflow, id, reply, success = 0;
char *rtype;
id = packet_get_int();
@@ -1850,6 +1850,17 @@
success = 1;
}
packet_check_eom();
+ } else if (strcmp(rtype, "xon-xoff") == 0) {
+ lflow = packet_get_char();
+ debug("client_input_channel_req: server %s local flow control",
+ lflow ? "allows" : "disallows");
+ if (!options.ignore_local_flow) {
+ if (lflow)
+ enter_lflow_mode();
+ else
+ leave_lflow_mode();
+ }
+ packet_check_eom();
}
if (reply) {
packet_start(success ?
--- openssh-4.5p1/readconf.c.orig 2006-09-01 05:38:37 +0000
+++ openssh-4.5p1/readconf.c 2006-12-09 21:42:24 +0000
@@ -129,7 +129,7 @@
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
- oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+ oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oIgnoreLocalFlow,
oDeprecated, oUnsupported
} OpCodes;
@@ -226,6 +226,7 @@
{ "tunneldevice", oTunnelDevice },
{ "localcommand", oLocalCommand },
{ "permitlocalcommand", oPermitLocalCommand },
+ { "ignorelocalflow", oIgnoreLocalFlow },
{ NULL, oBadOption }
};
@@ -915,6 +916,10 @@
intptr = &options->permit_local_command;
goto parse_flag;
+ case oIgnoreLocalFlow:
+ intptr = &options->ignore_local_flow;
+ goto parse_flag;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@@ -1065,6 +1070,7 @@
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
+ options->ignore_local_flow = -1;
}
/*
@@ -1199,6 +1205,8 @@
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
+ if (options->ignore_local_flow == -1)
+ options->ignore_local_flow = 1;
/* options->local_command should not be set by default */
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */
--- openssh-4.5p1/readconf.h.orig 2006-08-05 02:39:40 +0000
+++ openssh-4.5p1/readconf.h 2006-12-09 21:47:19 +0000
@@ -120,6 +120,7 @@
char *local_command;
int permit_local_command;
+ int ignore_local_flow;
} Options;
--- openssh-4.5p1/servconf.c.orig 2006-08-18 14:23:15 +0000
+++ openssh-4.5p1/servconf.c 2006-12-09 21:27:27 +0000
@@ -120,6 +120,7 @@
options->authorized_keys_file2 = NULL;
options->num_accept_env = 0;
options->permit_tun = -1;
+ options->use_local_flow = -1;
options->num_permitted_opens = -1;
options->adm_forced_command = NULL;
}
@@ -249,6 +250,8 @@
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
+ if (options->use_local_flow == -1)
+ options->use_local_flow = 0;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -293,6 +296,7 @@
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand,
sUsePrivilegeSeparation,
+ sUseLocalFlow,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -403,6 +407,7 @@
{ "match", sMatch, SSHCFG_ALL },
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
+ { "uselocalflow", sUseLocalFlow, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@@ -1253,6 +1258,10 @@
options->adm_forced_command = xstrdup(cp + len);
return 0;
+ case sUseLocalFlow:
+ intptr = &options->use_local_flow;
+ goto parse_flag;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
--- openssh-4.5p1/servconf.h.orig 2006-08-18 14:23:15 +0000
+++ openssh-4.5p1/servconf.h 2006-12-09 21:19:56 +0000
@@ -138,6 +138,8 @@
int use_pam; /* Enable auth via PAM */
+ int use_local_flow; /* Enable xon-xoff request */
+
int permit_tun;
int num_permitted_opens;
--- openssh-4.5p1/session.c.orig 2006-10-23 17:01:56 +0000
+++ openssh-4.5p1/session.c 2006-12-09 21:25:13 +0000
@@ -1854,6 +1854,16 @@
packet_check_eom();
session_proctitle(s);
+
+ if (options.use_local_flow) {
+ packet_start(SSH2_MSG_CHANNEL_REQUEST);
+ packet_put_int(s->chanid);
+ packet_put_cstring("xon-xoff");
+ packet_put_char(0);
+ packet_put_char(1);
+ packet_send();
+ }
+
return 1;
}
--- openssh-4.5p1/sshpty.h.orig 2006-08-05 02:39:41 +0000
+++ openssh-4.5p1/sshpty.h 2006-12-09 18:51:57 +0000
@@ -19,6 +19,8 @@
struct termios get_saved_tio(void);
void leave_raw_mode(void);
void enter_raw_mode(void);
+void leave_lflow_mode(void);
+void enter_lflow_mode(void);
int pty_allocate(int *, int *, char *, size_t);
void pty_release(const char *);
--- openssh-4.5p1/sshtty.c.orig 2006-08-05 02:39:41 +0000
+++ openssh-4.5p1/sshtty.c 2006-12-09 18:37:46 +0000
@@ -46,6 +46,7 @@
static struct termios _saved_tio;
static int _in_raw_mode = 0;
+static int _in_lflow_mode = 0;
struct termios
get_saved_tio(void)
@@ -54,6 +55,48 @@
}
void
+enter_lflow_mode(void)
+{
+ struct termios tio;
+
+ if (_in_lflow_mode)
+ return;
+
+ if (tcgetattr(fileno(stdin), &tio) == -1) {
+ perror("tcgetattr");
+ return;
+ }
+ if (_saved_tio.c_iflag & IXON)
+ tio.c_iflag |= IXON;
+ if (_saved_tio.c_iflag & IXOFF)
+ tio.c_iflag |= IXOFF;
+
+ if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) {
+ perror("tcsetattr");
+ } else
+ _in_lflow_mode = 1;
+}
+
+void
+leave_lflow_mode(void)
+{
+ struct termios tio;
+
+ if (!_in_lflow_mode)
+ return;
+
+ if (tcgetattr(fileno(stdin), &tio) == -1) {
+ perror("tcgetattr");
+ return;
+ }
+ tio.c_iflag &= ~(IXON | IXOFF);
+ if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) {
+ perror("tcsetattr");
+ } else
+ _in_lflow_mode = 0;
+}
+
+void
leave_raw_mode(void)
{
if (!_in_raw_mode)
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
http://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
|