X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/028094f4450d02fc8843aae576fccfee76492377..d59ac96c02231e8067fc89f55a31d7639eb11c6e:/misc.c diff --git a/misc.c b/misc.c index fba085d9..b260d89f 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.58 2006/07/11 20:07:25 stevesk Exp $ */ +/* $OpenBSD: misc.c,v 1.74 2009/12/25 19:40:21 stevesk Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -26,17 +26,23 @@ #include "includes.h" -#include #include +#include #include +#include #include +#include +#include +#include +#include #include #include #include #include +#include #ifdef HAVE_PATHS_H # include #include @@ -45,9 +51,9 @@ #include #endif +#include "xmalloc.h" #include "misc.h" #include "log.h" -#include "xmalloc.h" #include "ssh.h" /* remove newline at end of string */ @@ -115,6 +121,14 @@ unset_nonblock(int fd) return (0); } +const char * +ssh_gai_strerror(int gaierr) +{ + if (gaierr == EAI_SYSTEM) + return strerror(errno); + return gai_strerror(gaierr); +} + /* disable nagle on socket */ void set_nodelay(int fd) @@ -137,6 +151,47 @@ set_nodelay(int fd) error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); } +/* open a socket in the specified routing domain */ +int +socket_rdomain(int domain, int type, int protocol, int rdomain) +{ + int sock, ipproto = IPPROTO_IP; + + if ((sock = socket(domain, type, protocol)) == -1) + return (-1); + + if (rdomain == -1) + return (sock); + + switch (domain) { +#ifdef IPPROTO_IPV6 + case AF_INET6: + ipproto = IPPROTO_IPV6; + /* FALLTHROUGH */ +#endif + case AF_INET: +#ifdef USE_ROUTINGDOMAIN + debug2("socket %d af %d setting rdomain %d", + sock, domain, rdomain); + if (setsockopt(sock, ipproto, SO_RDOMAIN, &rdomain, + sizeof(rdomain)) == -1) { + debug("setsockopt SO_RDOMAIN: %.100s", + strerror(errno)); + close(sock); + return (-1); + } +#endif + break; + default: + debug("socket %d af %d does not support rdomain %d", + sock, domain, rdomain); + close(sock); + return (-1); + } + + return (sock); +} + /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" @@ -207,24 +262,34 @@ pwcopy(struct passwd *pw) /* * Convert ASCII string to TCP/IP port number. - * Port must be >0 and <=65535. - * Return 0 if invalid. + * Port must be >=0 and <=65535. + * Return -1 if invalid. */ int a2port(const char *s) { - long port; - char *endp; + long long port; + const char *errstr; - errno = 0; - port = strtol(s, &endp, 0); - if (s == endp || *endp != '\0' || - (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) || - port <= 0 || port > 65535) - return 0; + port = strtonum(s, 0, 65535, &errstr); + if (errstr != NULL) + return -1; + return (int)port; +} + +#ifdef USE_ROUTINGDOMAIN +int +a2rdomain(const char *s) +{ + long long rdomain; + const char *errstr; - return port; + rdomain = strtonum(s, 0, RT_TABLEID_MAX, &errstr); + if (errstr != NULL) + return -1; + return (int)rdomain; } +#endif int a2tun(const char *s, int *remote) @@ -520,7 +585,7 @@ tilde_expand_filename(const char *filename, uid_t uid) if ((pw = getpwnam(user)) == NULL) fatal("tilde_expand_filename: No such user %s", user); } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ - fatal("tilde_expand_filename: No such uid %d", uid); + fatal("tilde_expand_filename: No such uid %ld", (long)uid); if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret)) fatal("tilde_expand_filename: Path too long"); @@ -550,11 +615,11 @@ char * percent_expand(const char *string, ...) { #define EXPAND_MAX_KEYS 16 + u_int num_keys, i, j; struct { const char *key; const char *repl; } keys[EXPAND_MAX_KEYS]; - u_int num_keys, i, j; char buf[4096]; va_list ap; @@ -566,13 +631,12 @@ percent_expand(const char *string, ...) break; keys[num_keys].repl = va_arg(ap, char *); if (keys[num_keys].repl == NULL) - fatal("percent_expand: NULL replacement"); + fatal("%s: NULL replacement", __func__); } + if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) + fatal("%s: too many keys", __func__); va_end(ap); - if (num_keys >= EXPAND_MAX_KEYS) - fatal("percent_expand: too many keys"); - /* Expand string */ *buf = '\0'; for (i = 0; *string != '\0'; string++) { @@ -580,23 +644,24 @@ percent_expand(const char *string, ...) append: buf[i++] = *string; if (i >= sizeof(buf)) - fatal("percent_expand: string too long"); + fatal("%s: string too long", __func__); buf[i] = '\0'; continue; } string++; + /* %% case */ if (*string == '%') goto append; for (j = 0; j < num_keys; j++) { if (strchr(keys[j].key, *string) != NULL) { i = strlcat(buf, keys[j].repl, sizeof(buf)); if (i >= sizeof(buf)) - fatal("percent_expand: string too long"); + fatal("%s: string too long", __func__); break; } } if (j >= num_keys) - fatal("percent_expand: unknown key %%%c", *string); + fatal("%s: unknown key %%%c", __func__, *string); } return (xstrdup(buf)); #undef EXPAND_MAX_KEYS @@ -611,6 +676,8 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, u_long *lineno) { while (fgets(buf, bufsz, f) != NULL) { + if (buf[0] == '\0') + continue; (*lineno)++; if (buf[strlen(buf) - 1] == '\n' || feof(f)) { return 0; @@ -702,7 +769,8 @@ sanitise_stdfd(void) int nullfd, dupfd; if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { - fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); + fprintf(stderr, "Couldn't open /dev/null: %s\n", + strerror(errno)); exit(1); } while (++dupfd <= 2) { @@ -710,7 +778,7 @@ sanitise_stdfd(void) if (fcntl(dupfd, F_GETFL, 0) >= 0) continue; if (dup2(nullfd, dupfd) == -1) { - fprintf(stderr, "dup2: %s", strerror(errno)); + fprintf(stderr, "dup2: %s\n", strerror(errno)); exit(1); } } @@ -816,3 +884,34 @@ put_u16(void *vp, u_int16_t v) p[0] = (u_char)(v >> 8) & 0xff; p[1] = (u_char)v & 0xff; } + +void +ms_subtract_diff(struct timeval *start, int *ms) +{ + struct timeval diff, finish; + + gettimeofday(&finish, NULL); + timersub(&finish, start, &diff); + *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); +} + +void +ms_to_timeval(struct timeval *tv, int ms) +{ + if (ms < 0) + ms = 0; + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; +} + +void +sock_set_v6only(int s) +{ +#ifdef IPV6_V6ONLY + int on = 1; + + debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) + error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); +#endif +}