git: d4b3aefdf94f - main - netcat: add --crlf to convert LF into CRLF
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 28 Aug 2023 11:25:23 UTC
The branch main has been updated by gahr: URL: https://cgit.FreeBSD.org/src/commit/?id=d4b3aefdf94fe401f6bfc93a33b69e21dd7a634a commit d4b3aefdf94fe401f6bfc93a33b69e21dd7a634a Author: Pietro Cerutti <gahr@FreeBSD.org> AuthorDate: 2023-08-17 11:42:23 +0000 Commit: Pietro Cerutti <gahr@FreeBSD.org> CommitDate: 2023-08-28 10:58:17 +0000 netcat: add --crlf to convert LF into CRLF This adds the --crlf option to netcat, which triggers translation of \n characters into \r\n sequences in the input -> network direction. The Linux version of nc also supports this functionality with --crlf and -C. The OpenBSD version uses -C to specify client certificates. Our version is too old and doesn't have it, but I avoided adding -C anyway to ease future syncs with upstream. Attempts to upstream the feature were unsuccessful: https://marc.info/?t=169282068500001 Differential Revision: https://reviews.freebsd.org/D41489 --- contrib/netcat/nc.1 | 3 +++ contrib/netcat/netcat.c | 50 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1 index 9f8696135f35..2e34cdc586c3 100644 --- a/contrib/netcat/nc.1 +++ b/contrib/netcat/nc.1 @@ -42,6 +42,7 @@ .Op Fl i Ar interval .Op Fl -no-tcpopt .Op Fl -sctp +.Op Fl -crlf .Op Fl O Ar length .Op Fl P Ar proxy_username .Op Fl p Ar source_port @@ -104,6 +105,8 @@ to use IPv4 addresses only. Forces .Nm to use IPv6 addresses only. +.It Fl -crlf +Convert LF into CRLF when sending data over the network. .It Fl D Enable debugging on the socket. .It Fl d diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c index 65266b99c28e..279489a45e92 100644 --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/netcat.c @@ -94,6 +94,7 @@ int Nflag; /* shutdown() network socket */ int nflag; /* Don't do name look up */ int FreeBSD_Oflag; /* Do not use TCP options */ int FreeBSD_sctp; /* Use SCTP */ +int FreeBSD_crlf; /* Convert LF to CRLF */ char *Pflag; /* Proxy username */ char *pflag; /* Localport flag */ int rflag; /* Random ports flag */ @@ -136,7 +137,8 @@ void set_common_sockopts(int, int); int map_tos(char *, int *); void report_connect(const struct sockaddr *, socklen_t); void usage(int); -ssize_t drainbuf(int, unsigned char *, size_t *); +ssize_t write_wrapper(int, const void *, size_t); +ssize_t drainbuf(int, unsigned char *, size_t *, int); ssize_t fillbuf(int, unsigned char *, size_t *); #ifdef IPSEC @@ -165,6 +167,7 @@ main(int argc, char *argv[]) struct addrinfo proxyhints; char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; struct option longopts[] = { + { "crlf", no_argument, &FreeBSD_crlf, 1 }, { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 }, { "sctp", no_argument, &FreeBSD_sctp, 1 }, { "tun", required_argument, NULL, FREEBSD_TUN }, @@ -972,7 +975,7 @@ readwrite(int net_fd) /* try to write to network */ if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) { ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf, - &stdinbufpos); + &stdinbufpos, FreeBSD_crlf); if (ret == -1) pfd[POLL_NETOUT].fd = -1; /* buffer empty - remove self from polling */ @@ -1007,7 +1010,7 @@ readwrite(int net_fd) /* try to write to stdout */ if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) { ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf, - &netinbufpos); + &netinbufpos, 0); if (ret == -1) pfd[POLL_STDOUT].fd = -1; /* buffer empty - remove self from polling */ @@ -1037,17 +1040,41 @@ readwrite(int net_fd) } ssize_t -drainbuf(int fd, unsigned char *buf, size_t *bufpos) +write_wrapper(int fd, const void *buf, size_t buflen) { - ssize_t n; + ssize_t n = write(fd, buf, buflen); + /* don't treat EAGAIN, EINTR as error */ + return (n == -1 && (errno == EAGAIN || errno == EINTR)) ? -2 : n; +} + +ssize_t +drainbuf(int fd, unsigned char *buf, size_t *bufpos, int crlf) +{ + ssize_t n = *bufpos, n2 = 0; ssize_t adjust; + unsigned char *lf = NULL; + + if (crlf) { + lf = memchr(buf, '\n', *bufpos); + if (lf && (lf == buf || *(lf - 1) != '\r')) + n = lf - buf; + else + lf = NULL; + } + + if (n != 0) { + n = write_wrapper(fd, buf, n); + if (n <= 0) + return n; + } + + if (lf) { + n2 = write_wrapper(fd, "\r\n", 2); + if (n2 <= 0) + return n2; + n += 1; + } - n = write(fd, buf, *bufpos); - /* don't treat EAGAIN, EINTR as error */ - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = -2; - if (n <= 0) - return n; /* adjust buffer */ adjust = *bufpos - n; if (adjust > 0) @@ -1440,6 +1467,7 @@ help(void) fprintf(stderr, "\tCommand Summary:\n\ \t-4 Use IPv4\n\ \t-6 Use IPv6\n\ + \t--crlf Convert LF into CRLF when sending data over the network\n\ \t-D Enable the debug socket option\n\ \t-d Detach from stdin\n"); #ifdef IPSEC