diff options
Diffstat (limited to 'crypto/openssh/misc.c')
-rw-r--r-- | crypto/openssh/misc.c | 139 |
1 files changed, 132 insertions, 7 deletions
diff --git a/crypto/openssh/misc.c b/crypto/openssh/misc.c index a82e793..919b04e 100644 --- a/crypto/openssh/misc.c +++ b/crypto/openssh/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.80 2010/07/21 02:10:58 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.84 2010/11/21 01:01:13 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -35,9 +35,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> #include <netinet/tcp.h> #include <errno.h> @@ -850,16 +853,138 @@ ms_to_timeval(struct timeval *tv, int ms) tv->tv_usec = (ms % 1000) * 1000; } +void +bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) +{ + bw->buflen = buflen; + bw->rate = kbps; + bw->thresh = bw->rate; + bw->lamt = 0; + timerclear(&bw->bwstart); + timerclear(&bw->bwend); +} + +/* Callback from read/write loop to insert bandwidth-limiting delays */ +void +bandwidth_limit(struct bwlimit *bw, size_t read_len) +{ + u_int64_t waitlen; + struct timespec ts, rm; + + if (!timerisset(&bw->bwstart)) { + gettimeofday(&bw->bwstart, NULL); + return; + } + + bw->lamt += read_len; + if (bw->lamt < bw->thresh) + return; + + gettimeofday(&bw->bwend, NULL); + timersub(&bw->bwend, &bw->bwstart, &bw->bwend); + if (!timerisset(&bw->bwend)) + return; + + bw->lamt *= 8; + waitlen = (double)1000000L * bw->lamt / bw->rate; + + bw->bwstart.tv_sec = waitlen / 1000000L; + bw->bwstart.tv_usec = waitlen % 1000000L; + + if (timercmp(&bw->bwstart, &bw->bwend, >)) { + timersub(&bw->bwstart, &bw->bwend, &bw->bwend); + + /* Adjust the wait time */ + if (bw->bwend.tv_sec) { + bw->thresh /= 2; + if (bw->thresh < bw->buflen / 4) + bw->thresh = bw->buflen / 4; + } else if (bw->bwend.tv_usec < 10000) { + bw->thresh *= 2; + if (bw->thresh > bw->buflen * 8) + bw->thresh = bw->buflen * 8; + } + + TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); + while (nanosleep(&ts, &rm) == -1) { + if (errno != EINTR) + break; + ts = rm; + } + } + + bw->lamt = 0; + gettimeofday(&bw->bwstart, NULL); +} + +/* Make a template filename for mk[sd]temp() */ +void +mktemp_proto(char *s, size_t len) +{ + const char *tmpdir; + int r; + + if ((tmpdir = getenv("TMPDIR")) != NULL) { + r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); + if (r > 0 && (size_t)r < len) + return; + } + r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); + if (r < 0 || (size_t)r >= len) + fatal("%s: template string too short", __func__); +} + +static const struct { + const char *name; + int value; +} ipqos[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af14", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "lowdelay", IPTOS_LOWDELAY }, + { "throughput", IPTOS_THROUGHPUT }, + { "reliability", IPTOS_RELIABILITY }, + { NULL, -1 } +}; + int -timingsafe_bcmp(const void *b1, const void *b2, size_t n) +parse_ipqos(const char *cp) { - const unsigned char *p1 = b1, *p2 = b2; - int ret = 0; + u_int i; + char *ep; + long val; - for (; n > 0; n--) - ret |= *p1++ ^ *p2++; - return (ret != 0); + if (cp == NULL) + return -1; + for (i = 0; ipqos[i].name != NULL; i++) { + if (strcasecmp(cp, ipqos[i].name) == 0) + return ipqos[i].value; + } + /* Try parsing as an integer */ + val = strtol(cp, &ep, 0); + if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) + return -1; + return val; } + void sock_set_v6only(int s) { |