1 /* $OpenBSD: misc.c,v 1.95 2014/10/24 02:01:20 lteo Exp $ */ 2 /* 3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/ioctl.h> 29 #include <sys/socket.h> 30 #include <sys/un.h> 31 #include <sys/param.h> 32 33 #include <net/if.h> 34 #include <netinet/in.h> 35 #include <netinet/ip.h> 36 #include <netinet/tcp.h> 37 38 #include <ctype.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <netdb.h> 42 #include <paths.h> 43 #include <pwd.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "xmalloc.h" 51 #include "misc.h" 52 #include "log.h" 53 #include "ssh.h" 54 55 /* remove newline at end of string */ 56 char * 57 chop(char *s) 58 { 59 char *t = s; 60 while (*t) { 61 if (*t == '\n' || *t == '\r') { 62 *t = '\0'; 63 return s; 64 } 65 t++; 66 } 67 return s; 68 69 } 70 71 /* set/unset filedescriptor to non-blocking */ 72 int 73 set_nonblock(int fd) 74 { 75 int val; 76 77 val = fcntl(fd, F_GETFL, 0); 78 if (val < 0) { 79 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 80 return (-1); 81 } 82 if (val & O_NONBLOCK) { 83 debug3("fd %d is O_NONBLOCK", fd); 84 return (0); 85 } 86 debug2("fd %d setting O_NONBLOCK", fd); 87 val |= O_NONBLOCK; 88 if (fcntl(fd, F_SETFL, val) == -1) { 89 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 90 strerror(errno)); 91 return (-1); 92 } 93 return (0); 94 } 95 96 int 97 unset_nonblock(int fd) 98 { 99 int val; 100 101 val = fcntl(fd, F_GETFL, 0); 102 if (val < 0) { 103 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 104 return (-1); 105 } 106 if (!(val & O_NONBLOCK)) { 107 debug3("fd %d is not O_NONBLOCK", fd); 108 return (0); 109 } 110 debug("fd %d clearing O_NONBLOCK", fd); 111 val &= ~O_NONBLOCK; 112 if (fcntl(fd, F_SETFL, val) == -1) { 113 debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 114 fd, strerror(errno)); 115 return (-1); 116 } 117 return (0); 118 } 119 120 const char * 121 ssh_gai_strerror(int gaierr) 122 { 123 if (gaierr == EAI_SYSTEM && errno != 0) 124 return strerror(errno); 125 return gai_strerror(gaierr); 126 } 127 128 /* disable nagle on socket */ 129 void 130 set_nodelay(int fd) 131 { 132 int opt; 133 socklen_t optlen; 134 135 optlen = sizeof opt; 136 if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 137 debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 138 return; 139 } 140 if (opt == 1) { 141 debug2("fd %d is TCP_NODELAY", fd); 142 return; 143 } 144 opt = 1; 145 debug2("fd %d setting TCP_NODELAY", fd); 146 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 147 error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 148 } 149 150 /* Characters considered whitespace in strsep calls. */ 151 #define WHITESPACE " \t\r\n" 152 #define QUOTE "\"" 153 154 /* return next token in configuration line */ 155 char * 156 strdelim(char **s) 157 { 158 char *old; 159 int wspace = 0; 160 161 if (*s == NULL) 162 return NULL; 163 164 old = *s; 165 166 *s = strpbrk(*s, WHITESPACE QUOTE "="); 167 if (*s == NULL) 168 return (old); 169 170 if (*s[0] == '\"') { 171 memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 172 /* Find matching quote */ 173 if ((*s = strpbrk(*s, QUOTE)) == NULL) { 174 return (NULL); /* no matching quote */ 175 } else { 176 *s[0] = '\0'; 177 *s += strspn(*s + 1, WHITESPACE) + 1; 178 return (old); 179 } 180 } 181 182 /* Allow only one '=' to be skipped */ 183 if (*s[0] == '=') 184 wspace = 1; 185 *s[0] = '\0'; 186 187 /* Skip any extra whitespace after first token */ 188 *s += strspn(*s + 1, WHITESPACE) + 1; 189 if (*s[0] == '=' && !wspace) 190 *s += strspn(*s + 1, WHITESPACE) + 1; 191 192 return (old); 193 } 194 195 struct passwd * 196 pwcopy(struct passwd *pw) 197 { 198 struct passwd *copy = xcalloc(1, sizeof(*copy)); 199 200 copy->pw_name = xstrdup(pw->pw_name); 201 copy->pw_passwd = xstrdup(pw->pw_passwd); 202 copy->pw_gecos = xstrdup(pw->pw_gecos); 203 copy->pw_uid = pw->pw_uid; 204 copy->pw_gid = pw->pw_gid; 205 copy->pw_expire = pw->pw_expire; 206 copy->pw_change = pw->pw_change; 207 copy->pw_class = xstrdup(pw->pw_class); 208 copy->pw_dir = xstrdup(pw->pw_dir); 209 copy->pw_shell = xstrdup(pw->pw_shell); 210 return copy; 211 } 212 213 /* 214 * Convert ASCII string to TCP/IP port number. 215 * Port must be >=0 and <=65535. 216 * Return -1 if invalid. 217 */ 218 int 219 a2port(const char *s) 220 { 221 long long port; 222 const char *errstr; 223 224 port = strtonum(s, 0, 65535, &errstr); 225 if (errstr != NULL) 226 return -1; 227 return (int)port; 228 } 229 230 int 231 a2tun(const char *s, int *remote) 232 { 233 const char *errstr = NULL; 234 char *sp, *ep; 235 int tun; 236 237 if (remote != NULL) { 238 *remote = SSH_TUNID_ANY; 239 sp = xstrdup(s); 240 if ((ep = strchr(sp, ':')) == NULL) { 241 free(sp); 242 return (a2tun(s, NULL)); 243 } 244 ep[0] = '\0'; ep++; 245 *remote = a2tun(ep, NULL); 246 tun = a2tun(sp, NULL); 247 free(sp); 248 return (*remote == SSH_TUNID_ERR ? *remote : tun); 249 } 250 251 if (strcasecmp(s, "any") == 0) 252 return (SSH_TUNID_ANY); 253 254 tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 255 if (errstr != NULL) 256 return (SSH_TUNID_ERR); 257 258 return (tun); 259 } 260 261 #define SECONDS 1 262 #define MINUTES (SECONDS * 60) 263 #define HOURS (MINUTES * 60) 264 #define DAYS (HOURS * 24) 265 #define WEEKS (DAYS * 7) 266 267 /* 268 * Convert a time string into seconds; format is 269 * a sequence of: 270 * time[qualifier] 271 * 272 * Valid time qualifiers are: 273 * <none> seconds 274 * s|S seconds 275 * m|M minutes 276 * h|H hours 277 * d|D days 278 * w|W weeks 279 * 280 * Examples: 281 * 90m 90 minutes 282 * 1h30m 90 minutes 283 * 2d 2 days 284 * 1w 1 week 285 * 286 * Return -1 if time string is invalid. 287 */ 288 long 289 convtime(const char *s) 290 { 291 long total, secs; 292 const char *p; 293 char *endp; 294 295 errno = 0; 296 total = 0; 297 p = s; 298 299 if (p == NULL || *p == '\0') 300 return -1; 301 302 while (*p) { 303 secs = strtol(p, &endp, 10); 304 if (p == endp || 305 (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 306 secs < 0) 307 return -1; 308 309 switch (*endp++) { 310 case '\0': 311 endp--; 312 break; 313 case 's': 314 case 'S': 315 break; 316 case 'm': 317 case 'M': 318 secs *= MINUTES; 319 break; 320 case 'h': 321 case 'H': 322 secs *= HOURS; 323 break; 324 case 'd': 325 case 'D': 326 secs *= DAYS; 327 break; 328 case 'w': 329 case 'W': 330 secs *= WEEKS; 331 break; 332 default: 333 return -1; 334 } 335 total += secs; 336 if (total < 0) 337 return -1; 338 p = endp; 339 } 340 341 return total; 342 } 343 344 /* 345 * Returns a standardized host+port identifier string. 346 * Caller must free returned string. 347 */ 348 char * 349 put_host_port(const char *host, u_short port) 350 { 351 char *hoststr; 352 353 if (port == 0 || port == SSH_DEFAULT_PORT) 354 return(xstrdup(host)); 355 if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) 356 fatal("put_host_port: asprintf: %s", strerror(errno)); 357 debug3("put_host_port: %s", hoststr); 358 return hoststr; 359 } 360 361 /* 362 * Search for next delimiter between hostnames/addresses and ports. 363 * Argument may be modified (for termination). 364 * Returns *cp if parsing succeeds. 365 * *cp is set to the start of the next delimiter, if one was found. 366 * If this is the last field, *cp is set to NULL. 367 */ 368 char * 369 hpdelim(char **cp) 370 { 371 char *s, *old; 372 373 if (cp == NULL || *cp == NULL) 374 return NULL; 375 376 old = s = *cp; 377 if (*s == '[') { 378 if ((s = strchr(s, ']')) == NULL) 379 return NULL; 380 else 381 s++; 382 } else if ((s = strpbrk(s, ":/")) == NULL) 383 s = *cp + strlen(*cp); /* skip to end (see first case below) */ 384 385 switch (*s) { 386 case '\0': 387 *cp = NULL; /* no more fields*/ 388 break; 389 390 case ':': 391 case '/': 392 *s = '\0'; /* terminate */ 393 *cp = s + 1; 394 break; 395 396 default: 397 return NULL; 398 } 399 400 return old; 401 } 402 403 char * 404 cleanhostname(char *host) 405 { 406 if (*host == '[' && host[strlen(host) - 1] == ']') { 407 host[strlen(host) - 1] = '\0'; 408 return (host + 1); 409 } else 410 return host; 411 } 412 413 char * 414 colon(char *cp) 415 { 416 int flag = 0; 417 418 if (*cp == ':') /* Leading colon is part of file name. */ 419 return NULL; 420 if (*cp == '[') 421 flag = 1; 422 423 for (; *cp; ++cp) { 424 if (*cp == '@' && *(cp+1) == '[') 425 flag = 1; 426 if (*cp == ']' && *(cp+1) == ':' && flag) 427 return (cp+1); 428 if (*cp == ':' && !flag) 429 return (cp); 430 if (*cp == '/') 431 return NULL; 432 } 433 return NULL; 434 } 435 436 /* function to assist building execv() arguments */ 437 void 438 addargs(arglist *args, char *fmt, ...) 439 { 440 va_list ap; 441 char *cp; 442 u_int nalloc; 443 int r; 444 445 va_start(ap, fmt); 446 r = vasprintf(&cp, fmt, ap); 447 va_end(ap); 448 if (r == -1) 449 fatal("addargs: argument too long"); 450 451 nalloc = args->nalloc; 452 if (args->list == NULL) { 453 nalloc = 32; 454 args->num = 0; 455 } else if (args->num+2 >= nalloc) 456 nalloc *= 2; 457 458 args->list = xrealloc(args->list, nalloc, sizeof(char *)); 459 args->nalloc = nalloc; 460 args->list[args->num++] = cp; 461 args->list[args->num] = NULL; 462 } 463 464 void 465 replacearg(arglist *args, u_int which, char *fmt, ...) 466 { 467 va_list ap; 468 char *cp; 469 int r; 470 471 va_start(ap, fmt); 472 r = vasprintf(&cp, fmt, ap); 473 va_end(ap); 474 if (r == -1) 475 fatal("replacearg: argument too long"); 476 477 if (which >= args->num) 478 fatal("replacearg: tried to replace invalid arg %d >= %d", 479 which, args->num); 480 free(args->list[which]); 481 args->list[which] = cp; 482 } 483 484 void 485 freeargs(arglist *args) 486 { 487 u_int i; 488 489 if (args->list != NULL) { 490 for (i = 0; i < args->num; i++) 491 free(args->list[i]); 492 free(args->list); 493 args->nalloc = args->num = 0; 494 args->list = NULL; 495 } 496 } 497 498 /* 499 * Expands tildes in the file name. Returns data allocated by xmalloc. 500 * Warning: this calls getpw*. 501 */ 502 char * 503 tilde_expand_filename(const char *filename, uid_t uid) 504 { 505 const char *path, *sep; 506 char user[128], *ret; 507 struct passwd *pw; 508 u_int len, slash; 509 510 if (*filename != '~') 511 return (xstrdup(filename)); 512 filename++; 513 514 path = strchr(filename, '/'); 515 if (path != NULL && path > filename) { /* ~user/path */ 516 slash = path - filename; 517 if (slash > sizeof(user) - 1) 518 fatal("tilde_expand_filename: ~username too long"); 519 memcpy(user, filename, slash); 520 user[slash] = '\0'; 521 if ((pw = getpwnam(user)) == NULL) 522 fatal("tilde_expand_filename: No such user %s", user); 523 } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 524 fatal("tilde_expand_filename: No such uid %ld", (long)uid); 525 526 /* Make sure directory has a trailing '/' */ 527 len = strlen(pw->pw_dir); 528 if (len == 0 || pw->pw_dir[len - 1] != '/') 529 sep = "/"; 530 else 531 sep = ""; 532 533 /* Skip leading '/' from specified path */ 534 if (path != NULL) 535 filename = path + 1; 536 537 if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= MAXPATHLEN) 538 fatal("tilde_expand_filename: Path too long"); 539 540 return (ret); 541 } 542 543 /* 544 * Expand a string with a set of %[char] escapes. A number of escapes may be 545 * specified as (char *escape_chars, char *replacement) pairs. The list must 546 * be terminated by a NULL escape_char. Returns replaced string in memory 547 * allocated by xmalloc. 548 */ 549 char * 550 percent_expand(const char *string, ...) 551 { 552 #define EXPAND_MAX_KEYS 16 553 u_int num_keys, i, j; 554 struct { 555 const char *key; 556 const char *repl; 557 } keys[EXPAND_MAX_KEYS]; 558 char buf[4096]; 559 va_list ap; 560 561 /* Gather keys */ 562 va_start(ap, string); 563 for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 564 keys[num_keys].key = va_arg(ap, char *); 565 if (keys[num_keys].key == NULL) 566 break; 567 keys[num_keys].repl = va_arg(ap, char *); 568 if (keys[num_keys].repl == NULL) 569 fatal("%s: NULL replacement", __func__); 570 } 571 if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 572 fatal("%s: too many keys", __func__); 573 va_end(ap); 574 575 /* Expand string */ 576 *buf = '\0'; 577 for (i = 0; *string != '\0'; string++) { 578 if (*string != '%') { 579 append: 580 buf[i++] = *string; 581 if (i >= sizeof(buf)) 582 fatal("%s: string too long", __func__); 583 buf[i] = '\0'; 584 continue; 585 } 586 string++; 587 /* %% case */ 588 if (*string == '%') 589 goto append; 590 for (j = 0; j < num_keys; j++) { 591 if (strchr(keys[j].key, *string) != NULL) { 592 i = strlcat(buf, keys[j].repl, sizeof(buf)); 593 if (i >= sizeof(buf)) 594 fatal("%s: string too long", __func__); 595 break; 596 } 597 } 598 if (j >= num_keys) 599 fatal("%s: unknown key %%%c", __func__, *string); 600 } 601 return (xstrdup(buf)); 602 #undef EXPAND_MAX_KEYS 603 } 604 605 /* 606 * Read an entire line from a public key file into a static buffer, discarding 607 * lines that exceed the buffer size. Returns 0 on success, -1 on failure. 608 */ 609 int 610 read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 611 u_long *lineno) 612 { 613 while (fgets(buf, bufsz, f) != NULL) { 614 if (buf[0] == '\0') 615 continue; 616 (*lineno)++; 617 if (buf[strlen(buf) - 1] == '\n' || feof(f)) { 618 return 0; 619 } else { 620 debug("%s: %s line %lu exceeds size limit", __func__, 621 filename, *lineno); 622 /* discard remainder of line */ 623 while (fgetc(f) != '\n' && !feof(f)) 624 ; /* nothing */ 625 } 626 } 627 return -1; 628 } 629 630 int 631 tun_open(int tun, int mode) 632 { 633 struct ifreq ifr; 634 char name[100]; 635 int fd = -1, sock; 636 637 /* Open the tunnel device */ 638 if (tun <= SSH_TUNID_MAX) { 639 snprintf(name, sizeof(name), "/dev/tun%d", tun); 640 fd = open(name, O_RDWR); 641 } else if (tun == SSH_TUNID_ANY) { 642 for (tun = 100; tun >= 0; tun--) { 643 snprintf(name, sizeof(name), "/dev/tun%d", tun); 644 if ((fd = open(name, O_RDWR)) >= 0) 645 break; 646 } 647 } else { 648 debug("%s: invalid tunnel %u", __func__, tun); 649 return (-1); 650 } 651 652 if (fd < 0) { 653 debug("%s: %s open failed: %s", __func__, name, strerror(errno)); 654 return (-1); 655 } 656 657 debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 658 659 /* Set the tunnel device operation mode */ 660 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); 661 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 662 goto failed; 663 664 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) 665 goto failed; 666 667 /* Set interface mode */ 668 ifr.ifr_flags &= ~IFF_UP; 669 if (mode == SSH_TUNMODE_ETHERNET) 670 ifr.ifr_flags |= IFF_LINK0; 671 else 672 ifr.ifr_flags &= ~IFF_LINK0; 673 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 674 goto failed; 675 676 /* Bring interface up */ 677 ifr.ifr_flags |= IFF_UP; 678 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 679 goto failed; 680 681 close(sock); 682 return (fd); 683 684 failed: 685 if (fd >= 0) 686 close(fd); 687 if (sock >= 0) 688 close(sock); 689 debug("%s: failed to set %s mode %d: %s", __func__, name, 690 mode, strerror(errno)); 691 return (-1); 692 } 693 694 void 695 sanitise_stdfd(void) 696 { 697 int nullfd, dupfd; 698 699 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 700 fprintf(stderr, "Couldn't open /dev/null: %s\n", 701 strerror(errno)); 702 exit(1); 703 } 704 while (++dupfd <= 2) { 705 /* Only clobber closed fds */ 706 if (fcntl(dupfd, F_GETFL, 0) >= 0) 707 continue; 708 if (dup2(nullfd, dupfd) == -1) { 709 fprintf(stderr, "dup2: %s\n", strerror(errno)); 710 exit(1); 711 } 712 } 713 if (nullfd > 2) 714 close(nullfd); 715 } 716 717 char * 718 tohex(const void *vp, size_t l) 719 { 720 const u_char *p = (const u_char *)vp; 721 char b[3], *r; 722 size_t i, hl; 723 724 if (l > 65536) 725 return xstrdup("tohex: length > 65536"); 726 727 hl = l * 2 + 1; 728 r = xcalloc(1, hl); 729 for (i = 0; i < l; i++) { 730 snprintf(b, sizeof(b), "%02x", p[i]); 731 strlcat(r, b, hl); 732 } 733 return (r); 734 } 735 736 u_int64_t 737 get_u64(const void *vp) 738 { 739 const u_char *p = (const u_char *)vp; 740 u_int64_t v; 741 742 v = (u_int64_t)p[0] << 56; 743 v |= (u_int64_t)p[1] << 48; 744 v |= (u_int64_t)p[2] << 40; 745 v |= (u_int64_t)p[3] << 32; 746 v |= (u_int64_t)p[4] << 24; 747 v |= (u_int64_t)p[5] << 16; 748 v |= (u_int64_t)p[6] << 8; 749 v |= (u_int64_t)p[7]; 750 751 return (v); 752 } 753 754 u_int32_t 755 get_u32(const void *vp) 756 { 757 const u_char *p = (const u_char *)vp; 758 u_int32_t v; 759 760 v = (u_int32_t)p[0] << 24; 761 v |= (u_int32_t)p[1] << 16; 762 v |= (u_int32_t)p[2] << 8; 763 v |= (u_int32_t)p[3]; 764 765 return (v); 766 } 767 768 u_int32_t 769 get_u32_le(const void *vp) 770 { 771 const u_char *p = (const u_char *)vp; 772 u_int32_t v; 773 774 v = (u_int32_t)p[0]; 775 v |= (u_int32_t)p[1] << 8; 776 v |= (u_int32_t)p[2] << 16; 777 v |= (u_int32_t)p[3] << 24; 778 779 return (v); 780 } 781 782 u_int16_t 783 get_u16(const void *vp) 784 { 785 const u_char *p = (const u_char *)vp; 786 u_int16_t v; 787 788 v = (u_int16_t)p[0] << 8; 789 v |= (u_int16_t)p[1]; 790 791 return (v); 792 } 793 794 void 795 put_u64(void *vp, u_int64_t v) 796 { 797 u_char *p = (u_char *)vp; 798 799 p[0] = (u_char)(v >> 56) & 0xff; 800 p[1] = (u_char)(v >> 48) & 0xff; 801 p[2] = (u_char)(v >> 40) & 0xff; 802 p[3] = (u_char)(v >> 32) & 0xff; 803 p[4] = (u_char)(v >> 24) & 0xff; 804 p[5] = (u_char)(v >> 16) & 0xff; 805 p[6] = (u_char)(v >> 8) & 0xff; 806 p[7] = (u_char)v & 0xff; 807 } 808 809 void 810 put_u32(void *vp, u_int32_t v) 811 { 812 u_char *p = (u_char *)vp; 813 814 p[0] = (u_char)(v >> 24) & 0xff; 815 p[1] = (u_char)(v >> 16) & 0xff; 816 p[2] = (u_char)(v >> 8) & 0xff; 817 p[3] = (u_char)v & 0xff; 818 } 819 820 void 821 put_u32_le(void *vp, u_int32_t v) 822 { 823 u_char *p = (u_char *)vp; 824 825 p[0] = (u_char)v & 0xff; 826 p[1] = (u_char)(v >> 8) & 0xff; 827 p[2] = (u_char)(v >> 16) & 0xff; 828 p[3] = (u_char)(v >> 24) & 0xff; 829 } 830 831 void 832 put_u16(void *vp, u_int16_t v) 833 { 834 u_char *p = (u_char *)vp; 835 836 p[0] = (u_char)(v >> 8) & 0xff; 837 p[1] = (u_char)v & 0xff; 838 } 839 840 void 841 ms_subtract_diff(struct timeval *start, int *ms) 842 { 843 struct timeval diff, finish; 844 845 gettimeofday(&finish, NULL); 846 timersub(&finish, start, &diff); 847 *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 848 } 849 850 void 851 ms_to_timeval(struct timeval *tv, int ms) 852 { 853 if (ms < 0) 854 ms = 0; 855 tv->tv_sec = ms / 1000; 856 tv->tv_usec = (ms % 1000) * 1000; 857 } 858 859 time_t 860 monotime(void) 861 { 862 struct timespec ts; 863 864 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) 865 fatal("clock_gettime: %s", strerror(errno)); 866 867 return (ts.tv_sec); 868 } 869 870 void 871 bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 872 { 873 bw->buflen = buflen; 874 bw->rate = kbps; 875 bw->thresh = bw->rate; 876 bw->lamt = 0; 877 timerclear(&bw->bwstart); 878 timerclear(&bw->bwend); 879 } 880 881 /* Callback from read/write loop to insert bandwidth-limiting delays */ 882 void 883 bandwidth_limit(struct bwlimit *bw, size_t read_len) 884 { 885 u_int64_t waitlen; 886 struct timespec ts, rm; 887 888 if (!timerisset(&bw->bwstart)) { 889 gettimeofday(&bw->bwstart, NULL); 890 return; 891 } 892 893 bw->lamt += read_len; 894 if (bw->lamt < bw->thresh) 895 return; 896 897 gettimeofday(&bw->bwend, NULL); 898 timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 899 if (!timerisset(&bw->bwend)) 900 return; 901 902 bw->lamt *= 8; 903 waitlen = (double)1000000L * bw->lamt / bw->rate; 904 905 bw->bwstart.tv_sec = waitlen / 1000000L; 906 bw->bwstart.tv_usec = waitlen % 1000000L; 907 908 if (timercmp(&bw->bwstart, &bw->bwend, >)) { 909 timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 910 911 /* Adjust the wait time */ 912 if (bw->bwend.tv_sec) { 913 bw->thresh /= 2; 914 if (bw->thresh < bw->buflen / 4) 915 bw->thresh = bw->buflen / 4; 916 } else if (bw->bwend.tv_usec < 10000) { 917 bw->thresh *= 2; 918 if (bw->thresh > bw->buflen * 8) 919 bw->thresh = bw->buflen * 8; 920 } 921 922 TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 923 while (nanosleep(&ts, &rm) == -1) { 924 if (errno != EINTR) 925 break; 926 ts = rm; 927 } 928 } 929 930 bw->lamt = 0; 931 gettimeofday(&bw->bwstart, NULL); 932 } 933 934 /* Make a template filename for mk[sd]temp() */ 935 void 936 mktemp_proto(char *s, size_t len) 937 { 938 const char *tmpdir; 939 int r; 940 941 if ((tmpdir = getenv("TMPDIR")) != NULL) { 942 r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 943 if (r > 0 && (size_t)r < len) 944 return; 945 } 946 r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 947 if (r < 0 || (size_t)r >= len) 948 fatal("%s: template string too short", __func__); 949 } 950 951 static const struct { 952 const char *name; 953 int value; 954 } ipqos[] = { 955 { "af11", IPTOS_DSCP_AF11 }, 956 { "af12", IPTOS_DSCP_AF12 }, 957 { "af13", IPTOS_DSCP_AF13 }, 958 { "af21", IPTOS_DSCP_AF21 }, 959 { "af22", IPTOS_DSCP_AF22 }, 960 { "af23", IPTOS_DSCP_AF23 }, 961 { "af31", IPTOS_DSCP_AF31 }, 962 { "af32", IPTOS_DSCP_AF32 }, 963 { "af33", IPTOS_DSCP_AF33 }, 964 { "af41", IPTOS_DSCP_AF41 }, 965 { "af42", IPTOS_DSCP_AF42 }, 966 { "af43", IPTOS_DSCP_AF43 }, 967 { "cs0", IPTOS_DSCP_CS0 }, 968 { "cs1", IPTOS_DSCP_CS1 }, 969 { "cs2", IPTOS_DSCP_CS2 }, 970 { "cs3", IPTOS_DSCP_CS3 }, 971 { "cs4", IPTOS_DSCP_CS4 }, 972 { "cs5", IPTOS_DSCP_CS5 }, 973 { "cs6", IPTOS_DSCP_CS6 }, 974 { "cs7", IPTOS_DSCP_CS7 }, 975 { "ef", IPTOS_DSCP_EF }, 976 { "lowdelay", IPTOS_LOWDELAY }, 977 { "throughput", IPTOS_THROUGHPUT }, 978 { "reliability", IPTOS_RELIABILITY }, 979 { NULL, -1 } 980 }; 981 982 int 983 parse_ipqos(const char *cp) 984 { 985 u_int i; 986 char *ep; 987 long val; 988 989 if (cp == NULL) 990 return -1; 991 for (i = 0; ipqos[i].name != NULL; i++) { 992 if (strcasecmp(cp, ipqos[i].name) == 0) 993 return ipqos[i].value; 994 } 995 /* Try parsing as an integer */ 996 val = strtol(cp, &ep, 0); 997 if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 998 return -1; 999 return val; 1000 } 1001 1002 const char * 1003 iptos2str(int iptos) 1004 { 1005 int i; 1006 static char iptos_str[sizeof "0xff"]; 1007 1008 for (i = 0; ipqos[i].name != NULL; i++) { 1009 if (ipqos[i].value == iptos) 1010 return ipqos[i].name; 1011 } 1012 snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1013 return iptos_str; 1014 } 1015 1016 void 1017 lowercase(char *s) 1018 { 1019 for (; *s; s++) 1020 *s = tolower((u_char)*s); 1021 } 1022 1023 int 1024 unix_listener(const char *path, int backlog, int unlink_first) 1025 { 1026 struct sockaddr_un sunaddr; 1027 int saved_errno, sock; 1028 1029 memset(&sunaddr, 0, sizeof(sunaddr)); 1030 sunaddr.sun_family = AF_UNIX; 1031 if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1032 error("%s: \"%s\" too long for Unix domain socket", __func__, 1033 path); 1034 errno = ENAMETOOLONG; 1035 return -1; 1036 } 1037 1038 sock = socket(PF_UNIX, SOCK_STREAM, 0); 1039 if (sock < 0) { 1040 saved_errno = errno; 1041 error("socket: %.100s", strerror(errno)); 1042 errno = saved_errno; 1043 return -1; 1044 } 1045 if (unlink_first == 1) { 1046 if (unlink(path) != 0 && errno != ENOENT) 1047 error("unlink(%s): %.100s", path, strerror(errno)); 1048 } 1049 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { 1050 saved_errno = errno; 1051 error("bind: %.100s", strerror(errno)); 1052 close(sock); 1053 error("%s: cannot bind to path: %s", __func__, path); 1054 errno = saved_errno; 1055 return -1; 1056 } 1057 if (listen(sock, backlog) < 0) { 1058 saved_errno = errno; 1059 error("listen: %.100s", strerror(errno)); 1060 close(sock); 1061 unlink(path); 1062 error("%s: cannot listen on path: %s", __func__, path); 1063 errno = saved_errno; 1064 return -1; 1065 } 1066 return sock; 1067 } 1068