diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2023-06-05 01:11:33 +0200 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2023-06-06 11:54:39 +0200 |
commit | 48f4fd57802b5748235e18dc1ba367e675cd1109 (patch) | |
tree | d0488bd5db496ba239cc0d3a8afd18de8a3b7af3 | |
parent | 63e6314777f161fc71117424b8dd65df98fc6a6d (diff) | |
download | microcom-48f4fd57802b5748235e18dc1ba367e675cd1109.tar.gz microcom-48f4fd57802b5748235e18dc1ba367e675cd1109.tar.xz |
telnet: Quote IAC on sending
To send a single IAC in the payload, you have to send two IACs, the
first quoting the second. Otherwise the sequence will be interpreted as
a command by the other side.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-rw-r--r-- | telnet.c | 28 |
1 files changed, 27 insertions, 1 deletions
@@ -29,7 +29,33 @@ static ssize_t telnet_write(struct ios_ops *ios, const void *buf, size_t count) { - return write(ios->fd, buf, count); + size_t handled = 0; + ssize_t ret; + void *iac; + + /* + * To send an IAC character in the data stream, two IACs must be sent. + * So find the first IAC in the data to be send (if any), send the data + * before that IAC unquoted, then send the double IAC. Repeat until + * all IACs are handled. + */ + while ((iac = memchr(buf + handled, IAC, count - handled)) != NULL) { + if (iac - (buf + handled)) { + ret = write(ios->fd, buf + handled, iac - (buf + handled)); + if (ret < 0) + return ret; + handled += ret; + } else { + dprintf(ios->fd, "%c%c", IAC, IAC); + handled += 1; + } + } + + /* Send the remaining data that needs no quoting. */ + ret = write(ios->fd, buf + handled, count - handled); + if (ret < 0) + return ret; + return ret + handled; } static ssize_t telnet_read(struct ios_ops *ios, void *buf, size_t count) |