1 /* $OpenBSD: misc.c,v 1.80 2010/07/21 02:10:58 djm 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 "includes.h" 28 29 #include <sys/types.h> 30 #include <sys/ioctl.h> 31 #include <sys/socket.h> 32 #include <sys/param.h> 33 34 #include <stdarg.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 40 #include <netinet/in.h> 41 #include <netinet/tcp.h> 42 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <netdb.h> 46 #ifdef HAVE_PATHS_H 47 # include <paths.h> 48 #include <pwd.h> 49 #endif 50 #ifdef SSH_TUN_OPENBSD 51 #include <net/if.h> 52 #endif 53 54 #include "xmalloc.h" 55 #include "misc.h" 56 #include "log.h" 57 #include "ssh.h" 58 59 /* remove newline at end of string */ 60 char * 61 chop(char *s) 62 { 63 char *t = s; 64 while (*t) { 65 if (*t == '\n' || *t == '\r') { 66 *t = '\0'; 67 return s; 68 } 69 t++; 70 } 71 return s; 72 73 } 74 75 /* set/unset filedescriptor to non-blocking */ 76 int 77 set_nonblock(int fd) 78 { 79 int val; 80 81 val = fcntl(fd, F_GETFL, 0); 82 if (val < 0) { 83 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 84 return (-1); 85 } 86 if (val & O_NONBLOCK) { 87 debug3("fd %d is O_NONBLOCK", fd); 88 return (0); 89 } 90 debug2("fd %d setting O_NONBLOCK", fd); 91 val |= O_NONBLOCK; 92 if (fcntl(fd, F_SETFL, val) == -1) { 93 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 94 strerror(errno)); 95 return (-1); 96 } 97 return (0); 98 } 99 100 int 101 unset_nonblock(int fd) 102 { 103 int val; 104 105 val = fcntl(fd, F_GETFL, 0); 106 if (val < 0) { 107 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 108 return (-1); 109 } 110 if (!(val & O_NONBLOCK)) { 111 debug3("fd %d is not O_NONBLOCK", fd); 112 return (0); 113 } 114 debug("fd %d clearing O_NONBLOCK", fd); 115 val &= ~O_NONBLOCK; 116 if (fcntl(fd, F_SETFL, val) == -1) { 117 debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 118 fd, strerror(errno)); 119 return (-1); 120 } 121 return (0); 122 } 123 124 const char * 125 ssh_gai_strerror(int gaierr) 126 { 127 if (gaierr == EAI_SYSTEM) 128 return strerror(errno); 129 return gai_strerror(gaierr); 130 } 131 132 /* disable nagle on socket */ 133 void 134 set_nodelay(int fd) 135 { 136 int opt; 137 socklen_t optlen; 138 139 optlen = sizeof opt; 140 if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 141 debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 142 return; 143 } 144 if (opt == 1) { 145 debug2("fd %d is TCP_NODELAY", fd); 146 return; 147 } 148 opt = 1; 149 debug2("fd %d setting TCP_NODELAY", fd); 150 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 151 error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 152 } 153 154 /* Characters considered whitespace in strsep calls. */ 155 #define WHITESPACE " \t\r\n" 156 #define QUOTE "\"" 157 158 /* return next token in configuration line */ 159 char * 160 strdelim(char **s) 161 { 162 char *old; 163 int wspace = 0; 164 165 if (*s == NULL) 166 return NULL; 167 168 old = *s; 169 170 *s = strpbrk(*s, WHITESPACE QUOTE "="); 171 if (*s == NULL) 172 return (old); 173 174 if (*s[0] == '\"') { 175 memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 176 /* Find matching quote */ 177 if ((*s = strpbrk(*s, QUOTE)) == NULL) { 178 return (NULL); /* no matching quote */ 179 } else { 180 *s[0] = '\0'; 181 *s += strspn(*s + 1, WHITESPACE) + 1; 182 return (old); 183 } 184 } 185 186 /* Allow only one '=' to be skipped */ 187 if (*s[0] == '=') 188 wspace = 1; 189 *s[0] = '\0'; 190 191 /* Skip any extra whitespace after first token */ 192 *s += strspn(*s + 1, WHITESPACE) + 1; 193 if (*s[0] == '=' && !wspace) 194 *s += strspn(*s + 1, WHITESPACE) + 1; 195 196 return (old); 197 } 198 199 struct passwd * 200 pwcopy(struct passwd *pw) 201 { 202 struct passwd *copy = xcalloc(1, sizeof(*copy)); 203 204 copy->pw_name = xstrdup(pw->pw_name); 205 copy->pw_passwd = xstrdup(pw->pw_passwd); 206 copy->pw_gecos = xstrdup(pw->pw_gecos); 207 copy->pw_uid = pw->pw_uid; 208 copy->pw_gid = pw->pw_gid; 209 #ifdef HAVE_PW_EXPIRE_IN_PASSWD 210 copy->pw_expire = pw->pw_expire; 211 #endif 212 #ifdef HAVE_PW_CHANGE_IN_PASSWD 213 copy->pw_change = pw->pw_change; 214 #endif 215 #ifdef HAVE_PW_CLASS_IN_PASSWD 216 copy->pw_class = xstrdup(pw->pw_class); 217 #endif 218 copy->pw_dir = xstrdup(pw->pw_dir); 219 copy->pw_shell = xstrdup(pw->pw_shell); 220 return copy; 221 } 222 223 /* 224 * Convert ASCII string to TCP/IP port number. 225 * Port must be >=0 and <=65535. 226 * Return -1 if invalid. 227 */ 228 int 229 a2port(const char *s) 230 { 231 long long port; 232 const char *errstr; 233 234 port = strtonum(s, 0, 65535, &errstr); 235 if (errstr != NULL) 236 return -1; 237 return (int)port; 238 } 239 240 int 241 a2tun(const char *s, int *remote) 242 { 243 const char *errstr = NULL; 244 char *sp, *ep; 245 int tun; 246 247 if (remote != NULL) { 248 *remote = SSH_TUNID_ANY; 249 sp = xstrdup(s); 250 if ((ep = strchr(sp, ':')) == NULL) { 251 xfree(sp); 252 return (a2tun(s, NULL)); 253 } 254 ep[0] = '\0'; ep++; 255 *remote = a2tun(ep, NULL); 256 tun = a2tun(sp, NULL); 257 xfree(sp); 258 return (*remote == SSH_TUNID_ERR ? *remote : tun); 259 } 260 261 if (strcasecmp(s, "any") == 0) 262 return (SSH_TUNID_ANY); 263 264 tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 265 if (errstr != NULL) 266 return (SSH_TUNID_ERR); 267 268 return (tun); 269 } 270 271 #define SECONDS 1 272 #define MINUTES (SECONDS * 60) 273 #define HOURS (MINUTES * 60) 274 #define DAYS (HOURS * 24) 275 #define WEEKS (DAYS * 7) 276 277 /* 278 * Convert a time string into seconds; format is 279 * a sequence of: 280 * time[qualifier] 281 * 282 * Valid time qualifiers are: 283 * <none> seconds 284 * s|S seconds 285 * m|M minutes 286 * h|H hours 287 * d|D days 288 * w|W weeks 289 * 290 * Examples: 291 * 90m 90 minutes 292 * 1h30m 90 minutes 293 * 2d 2 days 294 * 1w 1 week 295 * 296 * Return -1 if time string is invalid. 297 */ 298 long 299 convtime(const char *s) 300 { 301 long total, secs; 302 const char *p; 303 char *endp; 304 305 errno = 0; 306 total = 0; 307 p = s; 308 309 if (p == NULL || *p == '\0') 310 return -1; 311 312 while (*p) { 313 secs = strtol(p, &endp, 10); 314 if (p == endp || 315 (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 316 secs < 0) 317 return -1; 318 319 switch (*endp++) { 320 case '\0': 321 endp--; 322 break; 323 case 's': 324 case 'S': 325 break; 326 case 'm': 327 case 'M': 328 secs *= MINUTES; 329 break; 330 case 'h': 331 case 'H': 332 secs *= HOURS; 333 break; 334 case 'd': 335 case 'D': 336 secs *= DAYS; 337 break; 338 case 'w': 339 case 'W': 340 secs *= WEEKS; 341 break; 342 default: 343 return -1; 344 } 345 total += secs; 346 if (total < 0) 347 return -1; 348 p = endp; 349 } 350 351 return total; 352 } 353 354 /* 355 * Returns a standardized host+port identifier string. 356 * Caller must free returned string. 357 */ 358 char * 359 put_host_port(const char *host, u_short port) 360 { 361 char *hoststr; 362 363 if (port == 0 || port == SSH_DEFAULT_PORT) 364 return(xstrdup(host)); 365 if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) 366 fatal("put_host_port: asprintf: %s", strerror(errno)); 367 debug3("put_host_port: %s", hoststr); 368 return hoststr; 369 } 370 371 /* 372 * Search for next delimiter between hostnames/addresses and ports. 373 * Argument may be modified (for termination). 374 * Returns *cp if parsing succeeds. 375 * *cp is set to the start of the next delimiter, if one was found. 376 * If this is the last field, *cp is set to NULL. 377 */ 378 char * 379 hpdelim(char **cp) 380 { 381 char *s, *old; 382 383 if (cp == NULL || *cp == NULL) 384 return NULL; 385 386 old = s = *cp; 387 if (*s == '[') { 388 if ((s = strchr(s, ']')) == NULL) 389 return NULL; 390 else 391 s++; 392 } else if ((s = strpbrk(s, ":/")) == NULL) 393 s = *cp + strlen(*cp); /* skip to end (see first case below) */ 394 395 switch (*s) { 396 case '\0': 397 *cp = NULL; /* no more fields*/ 398 break; 399 400 case ':': 401 case '/': 402 *s = '\0'; /* terminate */ 403 *cp = s + 1; 404 break; 405 406 default: 407 return NULL; 408 } 409 410 return old; 411 } 412 413 char * 414 cleanhostname(char *host) 415 { 416 if (*host == '[' && host[strlen(host) - 1] == ']') { 417 host[strlen(host) - 1] = '\0'; 418 return (host + 1); 419 } else 420 return host; 421 } 422 423 char * 424 colon(char *cp) 425 { 426 int flag = 0; 427 428 if (*cp == ':') /* Leading colon is part of file name. */ 429 return NULL; 430 if (*cp == '[') 431 flag = 1; 432 433 for (; *cp; ++cp) { 434 if (*cp == '@' && *(cp+1) == '[') 435 flag = 1; 436 if (*cp == ']' && *(cp+1) == ':' && flag) 437 return (cp+1); 438 if (*cp == ':' && !flag) 439 return (cp); 440 if (*cp == '/') 441 return NULL; 442 } 443 return NULL; 444 } 445 446 /* function to assist building execv() arguments */ 447 void 448 addargs(arglist *args, char *fmt, ...) 449 { 450 va_list ap; 451 char *cp; 452 u_int nalloc; 453 int r; 454 455 va_start(ap, fmt); 456 r = vasprintf(&cp, fmt, ap); 457 va_end(ap); 458 if (r == -1) 459 fatal("addargs: argument too long"); 460 461 nalloc = args->nalloc; 462 if (args->list == NULL) { 463 nalloc = 32; 464 args->num = 0; 465 } else if (args->num+2 >= nalloc) 466 nalloc *= 2; 467 468 args->list = xrealloc(args->list, nalloc, sizeof(char *)); 469 args->nalloc = nalloc; 470 args->list[args->num++] = cp; 471 args->list[args->num] = NULL; 472 } 473 474 void 475 replacearg(arglist *args, u_int which, char *fmt, ...) 476 { 477 va_list ap; 478 char *cp; 479 int r; 480 481 va_start(ap, fmt); 482 r = vasprintf(&cp, fmt, ap); 483 va_end(ap); 484 if (r == -1) 485 fatal("replacearg: argument too long"); 486 487 if (which >= args->num) 488 fatal("replacearg: tried to replace invalid arg %d >= %d", 489 which, args->num); 490 xfree(args->list[which]); 491 args->list[which] = cp; 492 } 493 494 void 495 freeargs(arglist *args) 496 { 497 u_int i; 498 499 if (args->list != NULL) { 500 for (i = 0; i < args->num; i++) 501 xfree(args->list[i]); 502 xfree(args->list); 503 args->nalloc = args->num = 0; 504 args->list = NULL; 505 } 506 } 507 508 /* 509 * Expands tildes in the file name. Returns data allocated by xmalloc. 510 * Warning: this calls getpw*. 511 */ 512 char * 513 tilde_expand_filename(const char *filename, uid_t uid) 514 { 515 const char *path; 516 char user[128], ret[MAXPATHLEN]; 517 struct passwd *pw; 518 u_int len, slash; 519 520 if (*filename != '~') 521 return (xstrdup(filename)); 522 filename++; 523 524 path = strchr(filename, '/'); 525 if (path != NULL && path > filename) { /* ~user/path */ 526 slash = path - filename; 527 if (slash > sizeof(user) - 1) 528 fatal("tilde_expand_filename: ~username too long"); 529 memcpy(user, filename, slash); 530 user[slash] = '\0'; 531 if ((pw = getpwnam(user)) == NULL) 532 fatal("tilde_expand_filename: No such user %s", user); 533 } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 534 fatal("tilde_expand_filename: No such uid %ld", (long)uid); 535 536 if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret)) 537 fatal("tilde_expand_filename: Path too long"); 538 539 /* Make sure directory has a trailing '/' */ 540 len = strlen(pw->pw_dir); 541 if ((len == 0 || pw->pw_dir[len - 1] != '/') && 542 strlcat(ret, "/", sizeof(ret)) >= sizeof(ret)) 543 fatal("tilde_expand_filename: Path too long"); 544 545 /* Skip leading '/' from specified path */ 546 if (path != NULL) 547 filename = path + 1; 548 if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret)) 549 fatal("tilde_expand_filename: Path too long"); 550 551 return (xstrdup(ret)); 552 } 553 554 /* 555 * Expand a string with a set of %[char] escapes. A number of escapes may be 556 * specified as (char *escape_chars, char *replacement) pairs. The list must 557 * be terminated by a NULL escape_char. Returns replaced string in memory 558 * allocated by xmalloc. 559 */ 560 char * 561 percent_expand(const char *string, ...) 562 { 563 #define EXPAND_MAX_KEYS 16 564 u_int num_keys, i, j; 565 struct { 566 const char *key; 567 const char *repl; 568 } keys[EXPAND_MAX_KEYS]; 569 char buf[4096]; 570 va_list ap; 571 572 /* Gather keys */ 573 va_start(ap, string); 574 for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 575 keys[num_keys].key = va_arg(ap, char *); 576 if (keys[num_keys].key == NULL) 577 break; 578 keys[num_keys].repl = va_arg(ap, char *); 579 if (keys[num_keys].repl == NULL) 580 fatal("%s: NULL replacement", __func__); 581 } 582 if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 583 fatal("%s: too many keys", __func__); 584 va_end(ap); 585 586 /* Expand string */ 587 *buf = '\0'; 588 for (i = 0; *string != '\0'; string++) { 589 if (*string != '%') { 590 append: 591 buf[i++] = *string; 592 if (i >= sizeof(buf)) 593 fatal("%s: string too long", __func__); 594 buf[i] = '\0'; 595 continue; 596 } 597 string++; 598 /* %% case */ 599 if (*string == '%') 600 goto append; 601 for (j = 0; j < num_keys; j++) { 602 if (strchr(keys[j].key, *string) != NULL) { 603 i = strlcat(buf, keys[j].repl, sizeof(buf)); 604 if (i >= sizeof(buf)) 605 fatal("%s: string too long", __func__); 606 break; 607 } 608 } 609 if (j >= num_keys) 610 fatal("%s: unknown key %%%c", __func__, *string); 611 } 612 return (xstrdup(buf)); 613 #undef EXPAND_MAX_KEYS 614 } 615 616 /* 617 * Read an entire line from a public key file into a static buffer, discarding 618 * lines that exceed the buffer size. Returns 0 on success, -1 on failure. 619 */ 620 int 621 read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 622 u_long *lineno) 623 { 624 while (fgets(buf, bufsz, f) != NULL) { 625 if (buf[0] == '\0') 626 continue; 627 (*lineno)++; 628 if (buf[strlen(buf) - 1] == '\n' || feof(f)) { 629 return 0; 630 } else { 631 debug("%s: %s line %lu exceeds size limit", __func__, 632 filename, *lineno); 633 /* discard remainder of line */ 634 while (fgetc(f) != '\n' && !feof(f)) 635 ; /* nothing */ 636 } 637 } 638 return -1; 639 } 640 641 int 642 tun_open(int tun, int mode) 643 { 644 #if defined(CUSTOM_SYS_TUN_OPEN) 645 return (sys_tun_open(tun, mode)); 646 #elif defined(SSH_TUN_OPENBSD) 647 struct ifreq ifr; 648 char name[100]; 649 int fd = -1, sock; 650 651 /* Open the tunnel device */ 652 if (tun <= SSH_TUNID_MAX) { 653 snprintf(name, sizeof(name), "/dev/tun%d", tun); 654 fd = open(name, O_RDWR); 655 } else if (tun == SSH_TUNID_ANY) { 656 for (tun = 100; tun >= 0; tun--) { 657 snprintf(name, sizeof(name), "/dev/tun%d", tun); 658 if ((fd = open(name, O_RDWR)) >= 0) 659 break; 660 } 661 } else { 662 debug("%s: invalid tunnel %u", __func__, tun); 663 return (-1); 664 } 665 666 if (fd < 0) { 667 debug("%s: %s open failed: %s", __func__, name, strerror(errno)); 668 return (-1); 669 } 670 671 debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 672 673 /* Set the tunnel device operation mode */ 674 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun); 675 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 676 goto failed; 677 678 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) 679 goto failed; 680 681 /* Set interface mode */ 682 ifr.ifr_flags &= ~IFF_UP; 683 if (mode == SSH_TUNMODE_ETHERNET) 684 ifr.ifr_flags |= IFF_LINK0; 685 else 686 ifr.ifr_flags &= ~IFF_LINK0; 687 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 688 goto failed; 689 690 /* Bring interface up */ 691 ifr.ifr_flags |= IFF_UP; 692 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) 693 goto failed; 694 695 close(sock); 696 return (fd); 697 698 failed: 699 if (fd >= 0) 700 close(fd); 701 if (sock >= 0) 702 close(sock); 703 debug("%s: failed to set %s mode %d: %s", __func__, name, 704 mode, strerror(errno)); 705 return (-1); 706 #else 707 error("Tunnel interfaces are not supported on this platform"); 708 return (-1); 709 #endif 710 } 711 712 void 713 sanitise_stdfd(void) 714 { 715 int nullfd, dupfd; 716 717 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 718 fprintf(stderr, "Couldn't open /dev/null: %s\n", 719 strerror(errno)); 720 exit(1); 721 } 722 while (++dupfd <= 2) { 723 /* Only clobber closed fds */ 724 if (fcntl(dupfd, F_GETFL, 0) >= 0) 725 continue; 726 if (dup2(nullfd, dupfd) == -1) { 727 fprintf(stderr, "dup2: %s\n", strerror(errno)); 728 exit(1); 729 } 730 } 731 if (nullfd > 2) 732 close(nullfd); 733 } 734 735 char * 736 tohex(const void *vp, size_t l) 737 { 738 const u_char *p = (const u_char *)vp; 739 char b[3], *r; 740 size_t i, hl; 741 742 if (l > 65536) 743 return xstrdup("tohex: length > 65536"); 744 745 hl = l * 2 + 1; 746 r = xcalloc(1, hl); 747 for (i = 0; i < l; i++) { 748 snprintf(b, sizeof(b), "%02x", p[i]); 749 strlcat(r, b, hl); 750 } 751 return (r); 752 } 753 754 u_int64_t 755 get_u64(const void *vp) 756 { 757 const u_char *p = (const u_char *)vp; 758 u_int64_t v; 759 760 v = (u_int64_t)p[0] << 56; 761 v |= (u_int64_t)p[1] << 48; 762 v |= (u_int64_t)p[2] << 40; 763 v |= (u_int64_t)p[3] << 32; 764 v |= (u_int64_t)p[4] << 24; 765 v |= (u_int64_t)p[5] << 16; 766 v |= (u_int64_t)p[6] << 8; 767 v |= (u_int64_t)p[7]; 768 769 return (v); 770 } 771 772 u_int32_t 773 get_u32(const void *vp) 774 { 775 const u_char *p = (const u_char *)vp; 776 u_int32_t v; 777 778 v = (u_int32_t)p[0] << 24; 779 v |= (u_int32_t)p[1] << 16; 780 v |= (u_int32_t)p[2] << 8; 781 v |= (u_int32_t)p[3]; 782 783 return (v); 784 } 785 786 u_int16_t 787 get_u16(const void *vp) 788 { 789 const u_char *p = (const u_char *)vp; 790 u_int16_t v; 791 792 v = (u_int16_t)p[0] << 8; 793 v |= (u_int16_t)p[1]; 794 795 return (v); 796 } 797 798 void 799 put_u64(void *vp, u_int64_t v) 800 { 801 u_char *p = (u_char *)vp; 802 803 p[0] = (u_char)(v >> 56) & 0xff; 804 p[1] = (u_char)(v >> 48) & 0xff; 805 p[2] = (u_char)(v >> 40) & 0xff; 806 p[3] = (u_char)(v >> 32) & 0xff; 807 p[4] = (u_char)(v >> 24) & 0xff; 808 p[5] = (u_char)(v >> 16) & 0xff; 809 p[6] = (u_char)(v >> 8) & 0xff; 810 p[7] = (u_char)v & 0xff; 811 } 812 813 void 814 put_u32(void *vp, u_int32_t v) 815 { 816 u_char *p = (u_char *)vp; 817 818 p[0] = (u_char)(v >> 24) & 0xff; 819 p[1] = (u_char)(v >> 16) & 0xff; 820 p[2] = (u_char)(v >> 8) & 0xff; 821 p[3] = (u_char)v & 0xff; 822 } 823 824 825 void 826 put_u16(void *vp, u_int16_t v) 827 { 828 u_char *p = (u_char *)vp; 829 830 p[0] = (u_char)(v >> 8) & 0xff; 831 p[1] = (u_char)v & 0xff; 832 } 833 834 void 835 ms_subtract_diff(struct timeval *start, int *ms) 836 { 837 struct timeval diff, finish; 838 839 gettimeofday(&finish, NULL); 840 timersub(&finish, start, &diff); 841 *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 842 } 843 844 void 845 ms_to_timeval(struct timeval *tv, int ms) 846 { 847 if (ms < 0) 848 ms = 0; 849 tv->tv_sec = ms / 1000; 850 tv->tv_usec = (ms % 1000) * 1000; 851 } 852 853 int 854 timingsafe_bcmp(const void *b1, const void *b2, size_t n) 855 { 856 const unsigned char *p1 = b1, *p2 = b2; 857 int ret = 0; 858 859 for (; n > 0; n--) 860 ret |= *p1++ ^ *p2++; 861 return (ret != 0); 862 } 863 void 864 sock_set_v6only(int s) 865 { 866 #ifdef IPV6_V6ONLY 867 int on = 1; 868 869 debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); 870 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) 871 error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); 872 #endif 873 } 874