diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 150 |
1 files changed, 137 insertions, 13 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.101 2016/01/20 09:22:39 dtucker Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.105 2016/07/15 00:24:30 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -86,9 +86,9 @@ set_nonblock(int fd) | |||
86 | { | 86 | { |
87 | int val; | 87 | int val; |
88 | 88 | ||
89 | val = fcntl(fd, F_GETFL, 0); | 89 | val = fcntl(fd, F_GETFL); |
90 | if (val < 0) { | 90 | if (val < 0) { |
91 | error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); | 91 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); |
92 | return (-1); | 92 | return (-1); |
93 | } | 93 | } |
94 | if (val & O_NONBLOCK) { | 94 | if (val & O_NONBLOCK) { |
@@ -110,9 +110,9 @@ unset_nonblock(int fd) | |||
110 | { | 110 | { |
111 | int val; | 111 | int val; |
112 | 112 | ||
113 | val = fcntl(fd, F_GETFL, 0); | 113 | val = fcntl(fd, F_GETFL); |
114 | if (val < 0) { | 114 | if (val < 0) { |
115 | error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); | 115 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); |
116 | return (-1); | 116 | return (-1); |
117 | } | 117 | } |
118 | if (!(val & O_NONBLOCK)) { | 118 | if (!(val & O_NONBLOCK)) { |
@@ -453,6 +453,67 @@ colon(char *cp) | |||
453 | return NULL; | 453 | return NULL; |
454 | } | 454 | } |
455 | 455 | ||
456 | /* | ||
457 | * Parse a [user@]host[:port] string. | ||
458 | * Caller must free returned user and host. | ||
459 | * Any of the pointer return arguments may be NULL (useful for syntax checking). | ||
460 | * If user was not specified then *userp will be set to NULL. | ||
461 | * If port was not specified then *portp will be -1. | ||
462 | * Returns 0 on success, -1 on failure. | ||
463 | */ | ||
464 | int | ||
465 | parse_user_host_port(const char *s, char **userp, char **hostp, int *portp) | ||
466 | { | ||
467 | char *sdup, *cp, *tmp; | ||
468 | char *user = NULL, *host = NULL; | ||
469 | int port = -1, ret = -1; | ||
470 | |||
471 | if (userp != NULL) | ||
472 | *userp = NULL; | ||
473 | if (hostp != NULL) | ||
474 | *hostp = NULL; | ||
475 | if (portp != NULL) | ||
476 | *portp = -1; | ||
477 | |||
478 | if ((sdup = tmp = strdup(s)) == NULL) | ||
479 | return -1; | ||
480 | /* Extract optional username */ | ||
481 | if ((cp = strchr(tmp, '@')) != NULL) { | ||
482 | *cp = '\0'; | ||
483 | if (*tmp == '\0') | ||
484 | goto out; | ||
485 | if ((user = strdup(tmp)) == NULL) | ||
486 | goto out; | ||
487 | tmp = cp + 1; | ||
488 | } | ||
489 | /* Extract mandatory hostname */ | ||
490 | if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') | ||
491 | goto out; | ||
492 | host = xstrdup(cleanhostname(cp)); | ||
493 | /* Convert and verify optional port */ | ||
494 | if (tmp != NULL && *tmp != '\0') { | ||
495 | if ((port = a2port(tmp)) <= 0) | ||
496 | goto out; | ||
497 | } | ||
498 | /* Success */ | ||
499 | if (userp != NULL) { | ||
500 | *userp = user; | ||
501 | user = NULL; | ||
502 | } | ||
503 | if (hostp != NULL) { | ||
504 | *hostp = host; | ||
505 | host = NULL; | ||
506 | } | ||
507 | if (portp != NULL) | ||
508 | *portp = port; | ||
509 | ret = 0; | ||
510 | out: | ||
511 | free(sdup); | ||
512 | free(user); | ||
513 | free(host); | ||
514 | return ret; | ||
515 | } | ||
516 | |||
456 | /* function to assist building execv() arguments */ | 517 | /* function to assist building execv() arguments */ |
457 | void | 518 | void |
458 | addargs(arglist *args, char *fmt, ...) | 519 | addargs(arglist *args, char *fmt, ...) |
@@ -796,16 +857,16 @@ sanitise_stdfd(void) | |||
796 | strerror(errno)); | 857 | strerror(errno)); |
797 | exit(1); | 858 | exit(1); |
798 | } | 859 | } |
799 | while (++dupfd <= 2) { | 860 | while (++dupfd <= STDERR_FILENO) { |
800 | /* Only clobber closed fds */ | 861 | /* Only populate closed fds. */ |
801 | if (fcntl(dupfd, F_GETFL, 0) >= 0) | 862 | if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { |
802 | continue; | 863 | if (dup2(nullfd, dupfd) == -1) { |
803 | if (dup2(nullfd, dupfd) == -1) { | 864 | fprintf(stderr, "dup2: %s\n", strerror(errno)); |
804 | fprintf(stderr, "dup2: %s\n", strerror(errno)); | 865 | exit(1); |
805 | exit(1); | 866 | } |
806 | } | 867 | } |
807 | } | 868 | } |
808 | if (nullfd > 2) | 869 | if (nullfd > STDERR_FILENO) |
809 | close(nullfd); | 870 | close(nullfd); |
810 | } | 871 | } |
811 | 872 | ||
@@ -976,6 +1037,31 @@ monotime(void) | |||
976 | return time(NULL); | 1037 | return time(NULL); |
977 | } | 1038 | } |
978 | 1039 | ||
1040 | double | ||
1041 | monotime_double(void) | ||
1042 | { | ||
1043 | #if defined(HAVE_CLOCK_GETTIME) && \ | ||
1044 | (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) | ||
1045 | struct timespec ts; | ||
1046 | static int gettime_failed = 0; | ||
1047 | |||
1048 | if (!gettime_failed) { | ||
1049 | #if defined(CLOCK_BOOTTIME) | ||
1050 | if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) | ||
1051 | return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); | ||
1052 | #endif | ||
1053 | #if defined(CLOCK_MONOTONIC) | ||
1054 | if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) | ||
1055 | return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); | ||
1056 | #endif | ||
1057 | debug3("clock_gettime: %s", strerror(errno)); | ||
1058 | gettime_failed = 1; | ||
1059 | } | ||
1060 | #endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ | ||
1061 | |||
1062 | return (double)time(NULL); | ||
1063 | } | ||
1064 | |||
979 | void | 1065 | void |
980 | bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) | 1066 | bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) |
981 | { | 1067 | { |
@@ -1186,3 +1272,41 @@ sock_set_v6only(int s) | |||
1186 | error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); | 1272 | error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); |
1187 | #endif | 1273 | #endif |
1188 | } | 1274 | } |
1275 | |||
1276 | /* | ||
1277 | * Compares two strings that maybe be NULL. Returns non-zero if strings | ||
1278 | * are both NULL or are identical, returns zero otherwise. | ||
1279 | */ | ||
1280 | static int | ||
1281 | strcmp_maybe_null(const char *a, const char *b) | ||
1282 | { | ||
1283 | if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) | ||
1284 | return 0; | ||
1285 | if (a != NULL && strcmp(a, b) != 0) | ||
1286 | return 0; | ||
1287 | return 1; | ||
1288 | } | ||
1289 | |||
1290 | /* | ||
1291 | * Compare two forwards, returning non-zero if they are identical or | ||
1292 | * zero otherwise. | ||
1293 | */ | ||
1294 | int | ||
1295 | forward_equals(const struct Forward *a, const struct Forward *b) | ||
1296 | { | ||
1297 | if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) | ||
1298 | return 0; | ||
1299 | if (a->listen_port != b->listen_port) | ||
1300 | return 0; | ||
1301 | if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) | ||
1302 | return 0; | ||
1303 | if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) | ||
1304 | return 0; | ||
1305 | if (a->connect_port != b->connect_port) | ||
1306 | return 0; | ||
1307 | if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) | ||
1308 | return 0; | ||
1309 | /* allocated_port and handle are not checked */ | ||
1310 | return 1; | ||
1311 | } | ||
1312 | |||