summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-01-23 14:01:54 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-01-23 14:01:54 +0000
commit2ab6bdb048f4b5f51b8b2742c87f561d9f368c05 (patch)
treef18b9fc7cf658ef640857f0180c9d13ebd88ba1b /usr.bin/ssh
parentdad96236271dcb55963b9fe8385f7812e71e67f7 (diff)
bandwidth limitation patch (scp -l) from niels@; ok todd@, deraadt@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/scp.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/usr.bin/ssh/scp.c b/usr.bin/ssh/scp.c
index feb96521b2c..2f195ee33e5 100644
--- a/usr.bin/ssh/scp.c
+++ b/usr.bin/ssh/scp.c
@@ -75,7 +75,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $");
+RCSID("$OpenBSD: scp.c,v 1.99 2003/01/23 14:01:53 markus Exp $");
#include "xmalloc.h"
#include "atomicio.h"
@@ -86,9 +86,14 @@ RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $");
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
+void bwlimit(int);
+
/* Struct for addargs */
arglist args;
+/* Bandwidth limit */
+off_t limit = 0;
+
/* Name of current file being transferred. */
char *curfile;
@@ -202,7 +207,8 @@ main(argc, argv)
char *argv[];
{
int ch, fflag, tflag, status;
- char *targ;
+ double speed;
+ char *targ, *endp;
extern char *optarg;
extern int optind;
@@ -213,7 +219,7 @@ main(argc, argv)
addargs(&args, "-oClearAllForwardings yes");
fflag = tflag = 0;
- while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1)
+ while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q46S:o:F:")) != -1)
switch (ch) {
/* User-visible flags. */
case '4':
@@ -233,6 +239,12 @@ main(argc, argv)
case 'B':
addargs(&args, "-oBatchmode yes");
break;
+ case 'l':
+ speed = strtod(optarg, &endp);
+ if (speed <= 0 || *endp != '\0')
+ usage();
+ limit = speed * 1024;
+ break;
case 'p':
pflag = 1;
break;
@@ -562,6 +574,8 @@ next: (void) close(fd);
haderr = result >= 0 ? EIO : errno;
statbytes += result;
}
+ if (limit)
+ bwlimit(amt);
}
if (showprogress)
stop_progress_meter();
@@ -632,6 +646,60 @@ rsource(name, statp)
}
void
+bwlimit(int amount)
+{
+ static struct timeval bwstart, bwend;
+ static int lamt, thresh = 16384;
+ u_int64_t wait;
+ struct timespec ts, rm;
+
+ if (!timerisset(&bwstart)) {
+ gettimeofday(&bwstart, NULL);
+ return;
+ }
+
+ lamt += amount;
+ if (lamt < thresh)
+ return;
+
+ gettimeofday(&bwend, NULL);
+ timersub(&bwend, &bwstart, &bwend);
+ if (!timerisset(&bwend))
+ return;
+
+ lamt *= 8;
+ wait = (double)1000000L * lamt / limit;
+
+ bwstart.tv_sec = wait / 1000000L;
+ bwstart.tv_usec = wait % 1000000L;
+
+ if (timercmp(&bwstart, &bwend, >)) {
+ timersub(&bwstart, &bwend, &bwend);
+
+ /* Adjust the wait time */
+ if (bwend.tv_sec) {
+ thresh /= 2;
+ if (thresh < 2048)
+ thresh = 2048;
+ } else if (bwend.tv_usec < 100) {
+ thresh *= 2;
+ if (thresh > 32768)
+ thresh = 32768;
+ }
+
+ TIMEVAL_TO_TIMESPEC(&bwend, &ts);
+ while (nanosleep(&ts, &rm) == -1) {
+ if (errno != EINTR)
+ break;
+ ts = rm;
+ }
+ }
+
+ lamt = 0;
+ gettimeofday(&bwstart, NULL);
+}
+
+void
sink(argc, argv)
int argc;
char *argv[];
@@ -828,6 +896,10 @@ bad: run_err("%s: %s", np, strerror(errno));
cp += j;
statbytes += j;
} while (amt > 0);
+
+ if (limit)
+ bwlimit(4096);
+
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
if (wrerr == NO) {
@@ -930,7 +1002,7 @@ usage(void)
{
(void) fprintf(stderr,
"usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
- " [-c cipher] [-i identity] [-o option]\n"
+ " [-c cipher] [-i identity] [-l limit] [-o option]\n"
" [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
exit(1);
}