upstream: add a -X option to both scp(1) and sftp(1) to allow

control over some SFTP protocol knobs: the copy buffer length and
the number of inflight requests, both of which are used during
upload/download.

Previously these could be controlled in sftp(1) using the -b/-R options.
This makes them available in both SFTP protocol clients using the same
option character sequence.

ok dtucker@

OpenBSD-Commit-ID: 27502bffc589776f5da1f31df8cb51abe9a15f1c
This commit is contained in:
djm@openbsd.org 2022-12-16 03:40:03 +00:00 committed by Darren Tucker
parent 5a7a7acab2
commit e555d5cad5
No known key found for this signature in database
5 changed files with 101 additions and 14 deletions

18
scp.1
View File

@ -8,9 +8,9 @@
.\" .\"
.\" Created: Sun May 7 00:14:37 1995 ylo .\" Created: Sun May 7 00:14:37 1995 ylo
.\" .\"
.\" $OpenBSD: scp.1,v 1.110 2022/09/19 21:39:16 djm Exp $ .\" $OpenBSD: scp.1,v 1.111 2022/12/16 03:40:03 djm Exp $
.\" .\"
.Dd $Mdocdate: September 19 2022 $ .Dd $Mdocdate: December 16 2022 $
.Dt SCP 1 .Dt SCP 1
.Os .Os
.Sh NAME .Sh NAME
@ -28,6 +28,7 @@
.Op Fl o Ar ssh_option .Op Fl o Ar ssh_option
.Op Fl P Ar port .Op Fl P Ar port
.Op Fl S Ar program .Op Fl S Ar program
.Op Fl X Ar sftp_option
.Ar source ... target .Ar source ... target
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
@ -278,6 +279,19 @@ and
to print debugging messages about their progress. to print debugging messages about their progress.
This is helpful in This is helpful in
debugging connection, authentication, and configuration problems. debugging connection, authentication, and configuration problems.
.It Fl X Ar sftp_option
Specify an option that controls aspects of SFTP protocol behaviour.
The valid options are:
.Bl -tag -width Ds
.It Cm nrequests Ns = Ns Ar value
Controls how many concurrent SFTP read or write requests may be in progress
at any point in time during a download or upload.
By default 64 requests may be active concurrently.
.It Cm buffer Ns = Ns Ar value
Controls the maximum buffer size for a single SFTP read/write operation used
during download or upload.
By default a 32KB buffer is used.
.El
.El .El
.Sh EXIT STATUS .Sh EXIT STATUS
.Ex -std scp .Ex -std scp

42
scp.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: scp.c,v 1.249 2022/10/24 21:51:55 djm Exp $ */ /* $OpenBSD: scp.c,v 1.250 2022/12/16 03:40:03 djm Exp $ */
/* /*
* scp - secure remote copy. This is basically patched BSD rcp which * scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd). * uses ssh to do the data transfer (instead of using rcmd).
@ -106,6 +106,9 @@
#include <libgen.h> #include <libgen.h>
#endif #endif
#include <limits.h> #include <limits.h>
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#include <locale.h> #include <locale.h>
#include <pwd.h> #include <pwd.h>
#include <signal.h> #include <signal.h>
@ -176,6 +179,10 @@ char *ssh_program = _PATH_SSH_PROGRAM;
pid_t do_cmd_pid = -1; pid_t do_cmd_pid = -1;
pid_t do_cmd_pid2 = -1; pid_t do_cmd_pid2 = -1;
/* SFTP copy parameters */
size_t sftp_copy_buflen;
size_t sftp_nrequests;
/* Needed for sftp */ /* Needed for sftp */
volatile sig_atomic_t interrupted = 0; volatile sig_atomic_t interrupted = 0;
@ -444,13 +451,14 @@ void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *,
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int ch, fflag, tflag, status, n; int ch, fflag, tflag, status, r, n;
char **newargv, *argv0; char **newargv, *argv0;
const char *errstr; const char *errstr;
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
enum scp_mode_e mode = MODE_SFTP; enum scp_mode_e mode = MODE_SFTP;
char *sftp_direct = NULL; char *sftp_direct = NULL;
long long llv;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
@ -480,7 +488,7 @@ main(int argc, char **argv)
fflag = Tflag = tflag = 0; fflag = Tflag = tflag = 0;
while ((ch = getopt(argc, argv, while ((ch = getopt(argc, argv,
"12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:")) != -1) { "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) {
switch (ch) { switch (ch) {
/* User-visible flags. */ /* User-visible flags. */
case '1': case '1':
@ -561,6 +569,31 @@ main(int argc, char **argv)
addargs(&remote_remote_args, "-q"); addargs(&remote_remote_args, "-q");
showprogress = 0; showprogress = 0;
break; break;
case 'X':
/* Please keep in sync with sftp.c -X */
if (strncmp(optarg, "buffer=", 7) == 0) {
r = scan_scaled(optarg + 7, &llv);
if (r == 0 && (llv <= 0 || llv > 256 * 1024)) {
r = -1;
errno = EINVAL;
}
if (r == -1) {
fatal("Invalid buffer size \"%s\": %s",
optarg + 7, strerror(errno));
}
sftp_copy_buflen = (size_t)llv;
} else if (strncmp(optarg, "nrequests=", 10) == 0) {
llv = strtonum(optarg + 10, 1, 256 * 1024,
&errstr);
if (errstr != NULL) {
fatal("Invalid number of requests "
"\"%s\": %s", optarg + 10, errstr);
}
sftp_nrequests = (size_t)llv;
} else {
fatal("Invalid -X option");
}
break;
/* Server options. */ /* Server options. */
case 'd': case 'd':
@ -972,7 +1005,8 @@ do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
reminp, remoutp, pidp) < 0) reminp, remoutp, pidp) < 0)
return NULL; return NULL;
} }
return do_init(*reminp, *remoutp, 32768, 64, limit_kbps); return do_init(*reminp, *remoutp,
sftp_copy_buflen, sftp_nrequests, limit_kbps);
} }
void void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.c,v 1.165 2022/09/19 10:43:12 djm Exp $ */ /* $OpenBSD: sftp-client.c,v 1.166 2022/12/16 03:40:03 djm Exp $ */
/* /*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
* *
@ -68,10 +68,10 @@
extern volatile sig_atomic_t interrupted; extern volatile sig_atomic_t interrupted;
extern int showprogress; extern int showprogress;
/* Default size of buffer for up/download */ /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */
#define DEFAULT_COPY_BUFLEN 32768 #define DEFAULT_COPY_BUFLEN 32768
/* Default number of concurrent outstanding requests */ /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */
#define DEFAULT_NUM_REQUESTS 64 #define DEFAULT_NUM_REQUESTS 64
/* Minimum amount of data to read at a time */ /* Minimum amount of data to read at a time */

18
sftp.1
View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.142 2022/09/19 21:39:16 djm Exp $ .\" $OpenBSD: sftp.1,v 1.143 2022/12/16 03:40:03 djm Exp $
.\" .\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\" .\"
@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: September 19 2022 $ .Dd $Mdocdate: December 16 2022 $
.Dt SFTP 1 .Dt SFTP 1
.Os .Os
.Sh NAME .Sh NAME
@ -44,6 +44,7 @@
.Op Fl R Ar num_requests .Op Fl R Ar num_requests
.Op Fl S Ar program .Op Fl S Ar program
.Op Fl s Ar subsystem | sftp_server .Op Fl s Ar subsystem | sftp_server
.Op Fl X Ar sftp_option
.Ar destination .Ar destination
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
@ -320,6 +321,19 @@ does not have an sftp subsystem configured.
.It Fl v .It Fl v
Raise logging level. Raise logging level.
This option is also passed to ssh. This option is also passed to ssh.
.It Fl X Ar sftp_option
Specify an option that controls aspects of SFTP protocol behaviour.
The valid options are:
.Bl -tag -width Ds
.It Cm nrequests Ns = Ns Ar value
Controls how many concurrent SFTP read or write requests may be in progress
at any point in time during a download or upload.
By default 64 requests may be active concurrently.
.It Cm buffer Ns = Ns Ar value
Controls the maximum buffer size for a single SFTP read/write operation used
during download or upload.
By default a 32KB buffer is used.
.El
.El .El
.Sh INTERACTIVE COMMANDS .Sh INTERACTIVE COMMANDS
Once in interactive mode, Once in interactive mode,

31
sftp.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.c,v 1.222 2022/09/19 10:46:00 djm Exp $ */ /* $OpenBSD: sftp.c,v 1.223 2022/12/16 03:40:03 djm Exp $ */
/* /*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
* *
@ -2431,7 +2431,7 @@ main(int argc, char **argv)
struct sftp_conn *conn; struct sftp_conn *conn;
size_t copy_buffer_len = 0; size_t copy_buffer_len = 0;
size_t num_requests = 0; size_t num_requests = 0;
long long limit_kbps = 0; long long llv, limit_kbps = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
@ -2449,7 +2449,7 @@ main(int argc, char **argv)
infile = stdin; infile = stdin;
while ((ch = getopt(argc, argv, while ((ch = getopt(argc, argv,
"1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) { "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:X:")) != -1) {
switch (ch) { switch (ch) {
/* Passed through to ssh(1) */ /* Passed through to ssh(1) */
case 'A': case 'A':
@ -2546,6 +2546,31 @@ main(int argc, char **argv)
ssh_program = optarg; ssh_program = optarg;
replacearg(&args, 0, "%s", ssh_program); replacearg(&args, 0, "%s", ssh_program);
break; break;
case 'X':
/* Please keep in sync with ssh.c -X */
if (strncmp(optarg, "buffer=", 7) == 0) {
r = scan_scaled(optarg + 7, &llv);
if (r == 0 && (llv <= 0 || llv > 256 * 1024)) {
r = -1;
errno = EINVAL;
}
if (r == -1) {
fatal("Invalid buffer size \"%s\": %s",
optarg + 7, strerror(errno));
}
copy_buffer_len = (size_t)llv;
} else if (strncmp(optarg, "nrequests=", 10) == 0) {
llv = strtonum(optarg + 10, 1, 256 * 1024,
&errstr);
if (errstr != NULL) {
fatal("Invalid number of requests "
"\"%s\": %s", optarg + 10, errstr);
}
num_requests = (size_t)llv;
} else {
fatal("Invalid -X option");
}
break;
case 'h': case 'h':
default: default:
usage(); usage();