summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/address.c116
-rw-r--r--src/common/address.h4
-rw-r--r--src/common/compat.c103
-rw-r--r--src/common/compat.h2
-rw-r--r--src/common/container.h5
-rw-r--r--src/common/crypto.c42
-rw-r--r--src/common/crypto.h4
-rw-r--r--src/common/include.am6
-rw-r--r--src/common/util.c189
-rw-r--r--src/common/util.h28
10 files changed, 204 insertions, 295 deletions
diff --git a/src/common/address.c b/src/common/address.c
index 6fc9fb3c47..227b4fbaee 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -817,7 +817,8 @@ tor_addr_is_loopback(const tor_addr_t *addr)
case AF_INET6: {
/* ::1 */
uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 1);
+ return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) &&
+ (ntohl(a32[3]) == 1);
}
case AF_INET:
/* 127.0.0.1 */
@@ -1565,32 +1566,6 @@ addr_mask_get_bits(uint32_t mask)
return -1;
}
-/** Compare two addresses <b>a1</b> and <b>a2</b> for equality under a
- * netmask of <b>mbits</b> bits. Return -1, 0, or 1.
- *
- * XXXX_IP6 Temporary function to allow masks as bitcounts everywhere. This
- * will be replaced with an IPv6-aware version as soon as 32-bit addresses are
- * no longer passed around.
- */
-int
-addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits)
-{
- if (bits > 32)
- bits = 32;
- else if (bits == 0)
- return 0;
-
- a1 >>= (32-bits);
- a2 >>= (32-bits);
-
- if (a1 < a2)
- return -1;
- else if (a1 > a2)
- return 1;
- else
- return 0;
-}
-
/** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the
* various *out pointers as appropriate. Return 0 on success, -1 on failure.
*/
@@ -1643,93 +1618,6 @@ parse_port_range(const char *port, uint16_t *port_min_out,
return 0;
}
-/** Parse a string <b>s</b> in the format of
- * (IP(/mask|/mask-bits)?|*)(:(*|port(-maxport))?)?, setting the various
- * *out pointers as appropriate. Return 0 on success, -1 on failure.
- */
-int
-parse_addr_and_port_range(const char *s, uint32_t *addr_out,
- maskbits_t *maskbits_out, uint16_t *port_min_out,
- uint16_t *port_max_out)
-{
- char *address;
- char *mask, *port, *endptr;
- struct in_addr in;
- int bits;
-
- tor_assert(s);
- tor_assert(addr_out);
- tor_assert(maskbits_out);
- tor_assert(port_min_out);
- tor_assert(port_max_out);
-
- address = tor_strdup(s);
- /* Break 'address' into separate strings.
- */
- mask = strchr(address,'/');
- port = strchr(mask?mask:address,':');
- if (mask)
- *mask++ = '\0';
- if (port)
- *port++ = '\0';
- /* Now "address" is the IP|'*' part...
- * "mask" is the Mask|Maskbits part...
- * and "port" is the *|port|min-max part.
- */
-
- if (strcmp(address,"*")==0) {
- *addr_out = 0;
- } else if (tor_inet_aton(address, &in) != 0) {
- *addr_out = ntohl(in.s_addr);
- } else {
- log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
- escaped(address));
- goto err;
- }
-
- if (!mask) {
- if (strcmp(address,"*")==0)
- *maskbits_out = 0;
- else
- *maskbits_out = 32;
- } else {
- endptr = NULL;
- bits = (int) strtol(mask, &endptr, 10);
- if (!*endptr) {
- /* strtol handled the whole mask. */
- if (bits < 0 || bits > 32) {
- log_warn(LD_GENERAL,
- "Bad number of mask bits on address range; rejecting.");
- goto err;
- }
- *maskbits_out = bits;
- } else if (tor_inet_aton(mask, &in) != 0) {
- bits = addr_mask_get_bits(ntohl(in.s_addr));
- if (bits < 0) {
- log_warn(LD_GENERAL,
- "Mask %s on address range isn't a prefix; dropping",
- escaped(mask));
- goto err;
- }
- *maskbits_out = bits;
- } else {
- log_warn(LD_GENERAL,
- "Malformed mask %s on address range; rejecting.",
- escaped(mask));
- goto err;
- }
- }
-
- if (parse_port_range(port, port_min_out, port_max_out)<0)
- goto err;
-
- tor_free(address);
- return 0;
- err:
- tor_free(address);
- return -1;
-}
-
/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
* write it as a string into the <b>buf_len</b>-byte buffer in
* <b>buf</b>.
diff --git a/src/common/address.h b/src/common/address.h
index 9cbc32ce9b..77e5855346 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -219,11 +219,7 @@ int addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
-int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
- maskbits_t *maskbits_out, uint16_t *port_min_out,
- uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
-int addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits);
/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
#define INET_NTOA_BUF_LEN 16
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
diff --git a/src/common/compat.c b/src/common/compat.c
index d7ce89479a..c97a4545c9 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -137,8 +137,13 @@ tor_open_cloexec(const char *path, int flags, unsigned mode)
fd = open(path, flags, mode);
#ifdef FD_CLOEXEC
- if (fd >= 0)
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (fd >= 0) {
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
#endif
return fd;
}
@@ -150,8 +155,13 @@ tor_fopen_cloexec(const char *path, const char *mode)
{
FILE *result = fopen(path, mode);
#ifdef FD_CLOEXEC
- if (result != NULL)
- fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+ if (result != NULL) {
+ if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ fclose(result);
+ return NULL;
+ }
+ }
#endif
return result;
}
@@ -1024,7 +1034,15 @@ tor_open_socket(int domain, int type, int protocol)
return s;
#if defined(FD_CLOEXEC)
- fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+#if defined(_WIN32)
+ closesocket(s);
+#else
+ close(s);
+#endif
+ return -1;
+ }
#endif
goto socket_ok; /* So that socket_ok will not be unused. */
@@ -1059,7 +1077,11 @@ tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
return s;
#if defined(FD_CLOEXEC)
- fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ close(s);
+ return TOR_INVALID_SOCKET;
+ }
#endif
goto socket_ok; /* So that socket_ok will not be unused. */
@@ -1083,17 +1105,31 @@ get_n_open_sockets(void)
return n;
}
-/** Turn <b>socket</b> into a nonblocking socket.
+/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
+ * on failure.
*/
-void
+int
set_socket_nonblocking(tor_socket_t socket)
{
#if defined(_WIN32)
unsigned long nonblocking = 1;
ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
#else
- fcntl(socket, F_SETFL, O_NONBLOCK);
+ int flags;
+
+ flags = fcntl(socket, F_GETFL, 0);
+ if (flags == -1) {
+ log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
+ return -1;
+ }
+ flags |= O_NONBLOCK;
+ if (fcntl(socket, F_SETFL, flags) == -1) {
+ log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
+ return -1;
+ }
#endif
+
+ return 0;
}
/**
@@ -1136,10 +1172,22 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
return -errno;
#if defined(FD_CLOEXEC)
- if (SOCKET_OK(fd[0]))
- fcntl(fd[0], F_SETFD, FD_CLOEXEC);
- if (SOCKET_OK(fd[1]))
- fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ if (SOCKET_OK(fd[0])) {
+ r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
+ if (SOCKET_OK(fd[1])) {
+ r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
#endif
goto sockets_ok; /* So that sockets_ok will not be unused. */
@@ -2265,8 +2313,33 @@ compute_num_cpus_impl(void)
return (int)info.dwNumberOfProcessors;
else
return -1;
-#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
- long cpus = sysconf(_SC_NPROCESSORS_CONF);
+#elif defined(HAVE_SYSCONF)
+#ifdef _SC_NPROCESSORS_CONF
+ long cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
+#else
+ long cpus_conf = -1;
+#endif
+#ifdef _SC_NPROCESSORS_ONLN
+ long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ long cpus_onln = -1;
+#endif
+ long cpus = -1;
+
+ if (cpus_conf > 0 && cpus_onln < 0) {
+ cpus = cpus_conf;
+ } else if (cpus_onln > 0 && cpus_conf < 0) {
+ cpus = cpus_onln;
+ } else if (cpus_onln > 0 && cpus_conf > 0) {
+ if (cpus_onln < cpus_conf) {
+ log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them "
+ "are available. Telling Tor to only use %ld. You can over"
+ "ride this with the NumCPUs option",
+ cpus_conf, cpus_onln, cpus_onln);
+ }
+ cpus = cpus_onln;
+ }
+
if (cpus >= 1 && cpus < INT_MAX)
return (int)cpus;
else
diff --git a/src/common/compat.h b/src/common/compat.h
index f9eb4ba0be..f0a34aae41 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -518,7 +518,7 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
-void set_socket_nonblocking(tor_socket_t socket);
+int set_socket_nonblocking(tor_socket_t socket);
int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
int network_init(void);
diff --git a/src/common/container.h b/src/common/container.h
index e247fb7ea6..1a68b8f67b 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -675,11 +675,6 @@ median_int32(int32_t *array, int n_elements)
{
return find_nth_int32(array, n_elements, (n_elements-1)/2);
}
-static INLINE long
-median_long(long *array, int n_elements)
-{
- return find_nth_long(array, n_elements, (n_elements-1)/2);
-}
#endif
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 22d57c7c8a..1b5b558a6f 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -113,8 +113,8 @@ crypto_get_rsa_padding_overhead(int padding)
{
switch (padding)
{
- case RSA_PKCS1_OAEP_PADDING: return 42;
- case RSA_PKCS1_PADDING: return 11;
+ case RSA_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD;
+ case RSA_PKCS1_PADDING: return PKCS1_PADDING_OVERHEAD;
default: tor_assert(0); return -1;
}
}
@@ -1294,23 +1294,6 @@ crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
return 0;
}
-/** Return true iff <b>s</b> is in the correct format for a fingerprint.
- */
-int
-crypto_pk_check_fingerprint_syntax(const char *s)
-{
- int i;
- for (i = 0; i < FINGERPRINT_LEN; ++i) {
- if ((i%5) == 4) {
- if (!TOR_ISSPACE(s[i])) return 0;
- } else {
- if (!TOR_ISXDIGIT(s[i])) return 0;
- }
- }
- if (s[FINGERPRINT_LEN]) return 0;
- return 1;
-}
-
/* symmetric crypto */
/** Return a pointer to the key set for the cipher in <b>env</b>.
@@ -1631,21 +1614,6 @@ crypto_digest_assign(crypto_digest_t *into,
memcpy(into,from,sizeof(crypto_digest_t));
}
-/** Compute the HMAC-SHA-1 of the <b>msg_len</b> bytes in <b>msg</b>, using
- * the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result
- * in <b>hmac_out</b>.
- */
-void
-crypto_hmac_sha1(char *hmac_out,
- const char *key, size_t key_len,
- const char *msg, size_t msg_len)
-{
- tor_assert(key_len < INT_MAX);
- tor_assert(msg_len < INT_MAX);
- HMAC(EVP_sha1(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
- (unsigned char*)hmac_out, NULL);
-}
-
/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
* the <b>key</b> of length <b>key_len</b>. Store the DIGEST256_LEN-byte
* result in <b>hmac_out</b>.
@@ -3000,6 +2968,12 @@ memwipe(void *mem, uint8_t byte, size_t sz)
}
#ifdef TOR_IS_MULTITHREADED
+
+#ifndef OPENSSL_THREADS
+#error OpenSSL has been built without thread support. Tor requires an \
+ OpenSSL library with thread support enabled.
+#endif
+
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
static void
openssl_locking_cb_(int mode, int n, const char *file, int line)
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 12fcfae27e..ee356c64bd 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -183,7 +183,6 @@ crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_get_digest(crypto_pk_t *pk, char *digest_out);
int crypto_pk_get_all_digests(crypto_pk_t *pk, digests_t *digests_out);
int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
-int crypto_pk_check_fingerprint_syntax(const char *s);
/* symmetric crypto */
const char *crypto_cipher_get_key(crypto_cipher_t *env);
@@ -218,9 +217,6 @@ void crypto_digest_get_digest(crypto_digest_t *digest,
crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest);
void crypto_digest_assign(crypto_digest_t *into,
const crypto_digest_t *from);
-void crypto_hmac_sha1(char *hmac_out,
- const char *key, size_t key_len,
- const char *msg, size_t msg_len);
void crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
diff --git a/src/common/include.am b/src/common/include.am
index b796ebfae8..68275cbcf7 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -14,9 +14,13 @@ else
libor_extra_source=
endif
+src_common_libcurve25519_donna_a_CFLAGS=
+
if BUILD_CURVE25519_DONNA
src_common_libcurve25519_donna_a_SOURCES=\
src/ext/curve25519_donna/curve25519-donna.c
+src_common_libcurve25519_donna_a_CFLAGS+=\
+ @F_OMIT_FRAME_POINTER@
noinst_LIBRARIES+=src/common/libcurve25519_donna.a
LIBDONNA=src/common/libcurve25519_donna.a
else
@@ -30,8 +34,6 @@ LIBDONNA=
endif
endif
-src_common_libcurve25519_donna_a_CFLAGS =
-
if CURVE25519_ENABLED
libcrypto_extra_source=src/common/crypto_curve25519.c
endif
diff --git a/src/common/util.c b/src/common/util.c
index 6a69635594..d297cb2dbc 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -865,6 +865,39 @@ tor_digest_is_zero(const char *digest)
return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
}
+/** Return true if <b>string</b> is a valid '<key>=[<value>]' string.
+ * <value> is optional, to indicate the empty string. Log at logging
+ * <b>severity</b> if something ugly happens. */
+int
+string_is_key_value(int severity, const char *string)
+{
+ /* position of equal sign in string */
+ const char *equal_sign_pos = NULL;
+
+ tor_assert(string);
+
+ if (strlen(string) < 2) { /* "x=" is shortest args string */
+ tor_log(severity, LD_GENERAL, "'%s' is too short to be a k=v value.",
+ escaped(string));
+ return 0;
+ }
+
+ equal_sign_pos = strchr(string, '=');
+ if (!equal_sign_pos) {
+ tor_log(severity, LD_GENERAL, "'%s' is not a k=v value.", escaped(string));
+ return 0;
+ }
+
+ /* validate that the '=' is not in the beginning of the string. */
+ if (equal_sign_pos == string) {
+ tor_log(severity, LD_GENERAL, "'%s' is not a valid k=v value.",
+ escaped(string));
+ return 0;
+ }
+
+ return 1;
+}
+
/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
int
tor_digest256_is_zero(const char *digest)
@@ -1176,119 +1209,50 @@ escaped(const char *s)
return escaped_val_;
}
-/** Rudimentary string wrapping code: given a un-wrapped <b>string</b> (no
- * newlines!), break the string into newline-terminated lines of no more than
- * <b>width</b> characters long (not counting newline) and insert them into
- * <b>out</b> in order. Precede the first line with prefix0, and subsequent
- * lines with prefixRest.
- */
-/* This uses a stupid greedy wrapping algorithm right now:
- * - For each line:
- * - Try to fit as much stuff as possible, but break on a space.
- * - If the first "word" of the line will extend beyond the allowable
- * width, break the word at the end of the width.
- */
-void
-wrap_string(smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest)
+/** Escape every ";" or "\" character of <b>string</b>. Use
+ * <b>escape_char</b> as the character to use for escaping.
+ * The returned string is allocated on the heap and it's the
+ * responsibility of the caller to free it. */
+char *
+tor_escape_str_for_socks_arg(const char *string)
{
- size_t p0Len, pRestLen, pCurLen;
- const char *eos, *prefixCur;
- tor_assert(out);
+ char *new_string = NULL;
+ char *new_cp = NULL;
+ size_t length, new_length;
+ static const char *chars_to_escape = ";\\";
+
tor_assert(string);
- tor_assert(width);
- if (!prefix0)
- prefix0 = "";
- if (!prefixRest)
- prefixRest = "";
-
- p0Len = strlen(prefix0);
- pRestLen = strlen(prefixRest);
- tor_assert(width > p0Len && width > pRestLen);
- eos = strchr(string, '\0');
- tor_assert(eos);
- pCurLen = p0Len;
- prefixCur = prefix0;
-
- while ((eos-string)+pCurLen > width) {
- const char *eol = string + width - pCurLen;
- while (eol > string && *eol != ' ')
- --eol;
- /* eol is now the last space that can fit, or the start of the string. */
- if (eol > string) {
- size_t line_len = (eol-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eol-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string = eol + 1;
- } else {
- size_t line_len = width + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, width - pCurLen);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string += width-pCurLen;
- }
- prefixCur = prefixRest;
- pCurLen = pRestLen;
- }
- if (string < eos) {
- size_t line_len = (eos-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eos-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
+ length = strlen(string);
+
+ if (!length) /* If we were given the empty string, return the same. */
+ return tor_strdup("");
+ /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
+ (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
+ if (length > (SIZE_MAX - 1)/2) /* check for overflow */
+ return NULL;
+
+ /* this should be enough even if all characters must be escaped */
+ new_length = (length * 2) + 1;
+
+ new_string = new_cp = tor_malloc(new_length);
+
+ while (*string) {
+ if (strchr(chars_to_escape, *string))
+ *new_cp++ = '\\';
+
+ *new_cp++ = *string++;
}
+
+ *new_cp = '\0'; /* NUL-terminate the new string */
+
+ return new_string;
}
/* =====
* Time
* ===== */
-/**
- * Converts struct timeval to a double value.
- * Preserves microsecond precision, but just barely.
- * Error is approx +/- 0.1 usec when dealing with epoch values.
- */
-double
-tv_to_double(const struct timeval *tv)
-{
- double conv = tv->tv_sec;
- conv += tv->tv_usec/1000000.0;
- return conv;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
-/**
- * Converts timeval to microseconds.
- */
-int64_t
-tv_to_usec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000000L;
- conv += tv->tv_usec;
- return conv;
-}
-
/** Return the number of microseconds elapsed between *start and *end.
*/
long
@@ -2537,10 +2501,13 @@ unescape_string(const char *s, char **result, size_t *size_out)
* key portion and *<b>value_out</b> to a new string holding the value portion
* of the line, and return a pointer to the start of the next line. If we run
* out of data, return a pointer to the end of the string. If we encounter an
- * error, return NULL.
+ * error, return NULL and set *<b>err_out</b> (if provided) to an error
+ * message.
*/
const char *
-parse_config_line_from_str(const char *line, char **key_out, char **value_out)
+parse_config_line_from_str_verbose(const char *line, char **key_out,
+ char **value_out,
+ const char **err_out)
{
/* I believe the file format here is supposed to be:
FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)?
@@ -2614,12 +2581,18 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out)
/* Find the end of the line. */
if (*line == '\"') { // XXX No continuation handling is done here
- if (!(line = unescape_string(line, value_out, NULL)))
- return NULL;
+ if (!(line = unescape_string(line, value_out, NULL))) {
+ if (err_out)
+ *err_out = "Invalid escape sequence in quoted string";
+ return NULL;
+ }
while (*line == ' ' || *line == '\t')
++line;
- if (*line && *line != '#' && *line != '\n')
+ if (*line && *line != '#' && *line != '\n') {
+ if (err_out)
+ *err_out = "Excess data after quoted string";
return NULL;
+ }
} else {
/* Look for the end of the line. */
while (*line && *line != '\n' && (*line != '#' || continuation)) {
diff --git a/src/common/util.h b/src/common/util.h
index ac88f1ca1c..0dd6da3a57 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -112,7 +112,6 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
#define tor_malloc(size) tor_malloc_(size DMALLOC_ARGS)
#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS)
#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS)
-#define tor_malloc_roundup(szp) _tor_malloc_roundup(szp DMALLOC_ARGS)
#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS)
#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS)
#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS)
@@ -173,6 +172,17 @@ int n_bits_set_u8(uint8_t v);
* overflow. */
#define CEIL_DIV(a,b) (((a)+(b)-1)/(b))
+/* Return <b>v</b> if it's between <b>min</b> and <b>max</b>. Otherwise
+ * return <b>min</b> if <b>v</b> is smaller than <b>min</b>, or <b>max</b> if
+ * <b>b</b> is larger than <b>max</b>.
+ *
+ * Requires that <b>min</b> is no more than <b>max</b>. May evaluate any of
+ * its arguments more than once! */
+#define CLAMP(min,v,max) \
+ ( ((v) < (min)) ? (min) : \
+ ((v) > (max)) ? (max) : \
+ (v) )
+
/* String manipulation */
/** Allowable characters in a hexadecimal string. */
@@ -209,15 +219,17 @@ const char *find_whitespace_eos(const char *s, const char *eos);
const char *find_str_at_start_of_line(const char *haystack,
const char *needle);
int string_is_C_identifier(const char *string);
+int string_is_key_value(int severity, const char *string);
int tor_mem_is_zero(const char *mem, size_t len);
int tor_digest_is_zero(const char *digest);
int tor_digest256_is_zero(const char *digest);
char *esc_for_log(const char *string) ATTR_MALLOC;
const char *escaped(const char *string);
+
+char *tor_escape_str_for_socks_arg(const char *string);
+
struct smartlist_t;
-void wrap_string(struct smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest);
int tor_vsscanf(const char *buf, const char *pattern, va_list ap)
#ifdef __GNUC__
__attribute__((format(scanf, 2, 0)))
@@ -240,9 +252,6 @@ void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
/* Time helpers */
-double tv_to_double(const struct timeval *tv);
-int64_t tv_to_msec(const struct timeval *tv);
-int64_t tv_to_usec(const struct timeval *tv);
long tv_udiff(const struct timeval *start, const struct timeval *end);
long tv_mdiff(const struct timeval *start, const struct timeval *end);
int tor_timegm(const struct tm *tm, time_t *time_out);
@@ -375,8 +384,11 @@ char *read_file_to_str(const char *filename, int flags, struct stat *stat_out)
char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
size_t *sz_out)
ATTR_MALLOC;
-const char *parse_config_line_from_str(const char *line,
- char **key_out, char **value_out);
+const char *parse_config_line_from_str_verbose(const char *line,
+ char **key_out, char **value_out,
+ const char **err_out);
+#define parse_config_line_from_str(line,key_out,value_out) \
+ parse_config_line_from_str_verbose((line),(key_out),(value_out),NULL)
char *expand_filename(const char *filename);
struct smartlist_t *tor_listdir(const char *dirname);
int path_is_relative(const char *filename);