diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-05-01 20:46:28 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-05-01 20:46:28 +0000 |
commit | 908ccb9dcdff19c6015a31726d2db5db5fef3ede (patch) | |
tree | 087a63bb6c490291ec12ae4f2e6f5c3dfc984ca4 /src | |
parent | ac4cb9bdd19bee938d1cb4cb9def727f92c8d2fc (diff) | |
download | tor-908ccb9dcdff19c6015a31726d2db5db5fef3ede.tar.gz tor-908ccb9dcdff19c6015a31726d2db5db5fef3ede.zip |
Handle windows socket errors correctly; comment most of common.
svn:r1756
Diffstat (limited to 'src')
-rw-r--r-- | src/common/crypto.c | 37 | ||||
-rw-r--r-- | src/common/crypto.h | 19 | ||||
-rw-r--r-- | src/common/fakepoll.c | 4 | ||||
-rw-r--r-- | src/common/fakepoll.h | 2 | ||||
-rw-r--r-- | src/common/torint.h | 5 | ||||
-rw-r--r-- | src/common/tortls.c | 84 | ||||
-rw-r--r-- | src/common/tortls.h | 6 | ||||
-rw-r--r-- | src/common/util.c | 237 | ||||
-rw-r--r-- | src/common/util.h | 43 | ||||
-rw-r--r-- | src/or/buffers.c | 19 | ||||
-rw-r--r-- | src/or/connection.c | 19 | ||||
-rw-r--r-- | src/or/connection_edge.c | 2 | ||||
-rw-r--r-- | src/or/connection_or.c | 2 | ||||
-rw-r--r-- | src/or/directory.c | 2 | ||||
-rw-r--r-- | src/or/main.c | 6 | ||||
-rw-r--r-- | src/or/test.c | 38 |
16 files changed, 385 insertions, 140 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index 99d6d79367..a591d92057 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -54,8 +54,7 @@ #define OPENSSL_095 #endif -/* - * Certain functions that return a success code in OpenSSL 0.9.6 return void +/* Certain functions that return a success code in OpenSSL 0.9.6 return void * (and don't indicate errors) in OpenSSL version 0.9.5. * * [OpenSSL 0.9.5 matters, because it ships with Redhat 6.2.] @@ -66,12 +65,14 @@ #define RETURN_SSL_OUTCOME(exp) return !(exp) #endif +/* Macro: is k a valid RSA public or private key? */ #define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n) +/* Macro: is k a valid RSA private key? */ #define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p) struct crypto_pk_env_t { - int refs; /* reference counting; so we don't have to copy keys */ + int refs; /* reference counting so we don't have to copy keys */ RSA *key; }; @@ -85,6 +86,8 @@ struct crypto_dh_env_t { DH *dh; }; +/* Return the number of bytes added by padding method 'padding' + */ static INLINE int crypto_get_rsa_padding_overhead(int padding) { switch(padding) @@ -96,6 +99,8 @@ crypto_get_rsa_padding_overhead(int padding) { } } +/* Given a padding method 'padding', return the correct OpenSSL constant. + */ static INLINE int crypto_get_rsa_padding(int padding) { switch(padding) @@ -107,10 +112,12 @@ crypto_get_rsa_padding(int padding) { } } +/* Boolen: has OpenSSL's crypto been initialized? */ static int _crypto_global_initialized = 0; - -/* errors */ +/* Log all pending crypto errors at level 'severity'. Use 'doing' to describe + * our current activities. + */ static void crypto_log_errors(int severity, const char *doing) { @@ -128,6 +135,8 @@ crypto_log_errors(int severity, const char *doing) } } } +/* Initialize the crypto library. + */ int crypto_global_init() { if (!_crypto_global_initialized) { @@ -137,13 +146,15 @@ int crypto_global_init() return 0; } +/* Uninitialize the crypto library. + */ int crypto_global_cleanup() { ERR_free_strings(); return 0; } -/* used by tortls.c */ +/* used by tortls.c: wrap an RSA* in a crypto_pk_env_t. */ crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa) { crypto_pk_env_t *env; @@ -154,13 +165,14 @@ crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa) return env; } -/* used by tortls.c */ +/* used by tortls.c: return the RSA* from a crypto_pk_env_t */ RSA *_crypto_pk_env_get_rsa(crypto_pk_env_t *env) { return env->key; } -/* used by tortls.c */ +/* used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_env_t. Iff + * private is set, include the private-key portion of the key. */ EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private) { RSA *key = NULL; @@ -186,11 +198,16 @@ EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private) return NULL; } +/* Used by tortls.c: Get the DH* from a crypto_dh_env_t. + */ DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh) { return dh->dh; } +/* Allocate and return storage for a public key. The key itself will not yet + * be set. + */ crypto_pk_env_t *crypto_new_pk_env(void) { RSA *rsa; @@ -200,6 +217,8 @@ crypto_pk_env_t *crypto_new_pk_env(void) return _crypto_new_pk_env_rsa(rsa); } +/* + */ void crypto_free_pk_env(crypto_pk_env_t *env) { tor_assert(env); @@ -273,7 +292,7 @@ int crypto_pk_generate_key(crypto_pk_env_t *env) if (env->key) RSA_free(env->key); - env->key = RSA_generate_key(PK_BITS,65537, NULL, NULL); + env->key = RSA_generate_key(PK_BYTES*8,65537, NULL, NULL); if (!env->key) { crypto_log_errors(LOG_WARN, "generating RSA key"); return -1; diff --git a/src/common/crypto.h b/src/common/crypto.h index 510954a852..d867d4d601 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -7,21 +7,29 @@ #include <stdio.h> +/* Length of the output of our message digest. */ #define DIGEST_LEN 20 +/* Length of our symmetric cipher's keys. */ #define CIPHER_KEY_LEN 16 -#define PK_BITS 1024 -#define PK_BYTES (PK_BITS/8) -#define DH_BITS 1024 -#define DH_BYTES (DH_BITS/8) -#define CRYPTO_DH_SIZE DH_BYTES +/* Length of our public keys. */ +#define PK_BYTES (1024/8) +/* Length of our DH keys. */ +#define DH_BYTES (1024/8) +/* Constants used to indicate disired public-key padding functions. */ #define PK_NO_PADDING 60000 #define PK_PKCS1_PADDING 60001 #define PK_PKCS1_OAEP_PADDING 60002 +/* Bytes added for PKCS1 padding. */ #define PKCS1_PADDING_OVERHEAD 11 +/* Bytes added for PKCS1-OAEP padding. */ #define PKCS1_OAEP_PADDING_OVERHEAD 42 +/* Length of encoded public key fingerprints, including space and NUL. */ +#define FINGERPRINT_LEN 49 + + typedef struct crypto_pk_env_t crypto_pk_env_t; typedef struct crypto_cipher_env_t crypto_cipher_env_t; typedef struct crypto_digest_env_t crypto_digest_env_t; @@ -64,7 +72,6 @@ int crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, const unsigned char *from, int fromlen, unsigned char *to,int padding); -#define FINGERPRINT_LEN 49 int crypto_pk_asn1_encode(crypto_pk_env_t *pk, char *dest, int dest_len); crypto_pk_env_t *crypto_pk_asn1_decode(const char *str, int len); int crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out); diff --git a/src/common/fakepoll.c b/src/common/fakepoll.c index 37258d8321..5209bedb48 100644 --- a/src/common/fakepoll.c +++ b/src/common/fakepoll.c @@ -2,7 +2,9 @@ /* See LICENSE for licensing information */ /* $Id$ */ -/* On systems where 'poll' doesn't exist, fake it with 'select'. */ +/***** + * fakepoll.c: On systems where 'poll' doesn't exist, fake it with 'select'. + *****/ #include "orconfig.h" #include "fakepoll.h" diff --git a/src/common/fakepoll.h b/src/common/fakepoll.h index 47490326c2..4d0d9ce524 100644 --- a/src/common/fakepoll.h +++ b/src/common/fakepoll.h @@ -16,7 +16,7 @@ #endif /* If _POLL_EMUL_H_ is defined, then poll is just a just a thin wrapper around - * select. On Mac OS 10.3, this wrapper is kinda flakey, and we should + * select. On Mac OS 10.3, this wrapper is kinda flaky, and we should * use our own. */ #if (defined(HAVE_POLL_H)||defined(HAVE_SYS_POLL_H)) && !defined(_POLL_EMUL_H_) diff --git a/src/common/torint.h b/src/common/torint.h index c80404a468..80ee48820d 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -2,11 +2,16 @@ /* See LICENSE for licensing information */ /* $Id$ */ +/***** + * torint.h: Header file to define uint32_t and friends. + *****/ + #ifndef __TORINT_H #define __TORINT_H #include "orconfig.h" + #ifdef HAVE_STDINT_H #include <stdint.h> #endif diff --git a/src/common/tortls.c b/src/common/tortls.c index e46b1a9097..05cc0200e2 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -2,10 +2,11 @@ /* See LICENSE for licensing information */ /* $Id$ */ -/* TLS wrappers for The Onion Router. (Unlike other tor functions, these +/***** + * tortls.c: TLS wrappers for Tor. (Unlike other tor functions, these * are prefixed with tor_ in order to avoid conflicting with OpenSSL * functions and variables.) - */ + *****/ #include "./crypto.h" #include "./tortls.h" @@ -28,17 +29,20 @@ /* How much clock skew do we tolerate when checking certificates? (sec) */ #define CERT_ALLOW_SKEW (90*60) -struct tor_tls_context_st { +typedef struct tor_tls_context_st { SSL_CTX *ctx; -}; +} tor_tls_context; +/* Holds a SSL object and it associated data. + */ struct tor_tls_st { SSL *ssl; - int socket; + int socket; /* The underlying fd. */ enum { TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED - } state; + } state; /* The current SSL state, depending on which operatios have + * completed successfully. */ int isServer; int wantwrite_n; /* 0 normally, >0 if we returned wantwrite last time */ }; @@ -49,10 +53,12 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname_sign, unsigned int lifetime); -/* global tls context, keep it here because nobody else needs to touch it */ +/* Global tls context. We keep it here because nobody else needs to touch it */ static tor_tls_context *global_tls_context = NULL; +/* True iff tor_tls_init() has been called. */ static int tls_library_is_initialized = 0; +/* Module-internal error codes. */ #define _TOR_TLS_SYSCALL -6 #define _TOR_TLS_ZERORETURN -5 @@ -61,6 +67,9 @@ EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private); crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa); DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh); +/* Log all pending tls errors at level 'severity'. Use 'doing' to describe + * our current activities. + */ static void tls_log_errors(int severity, const char *doing) { @@ -82,6 +91,16 @@ tls_log_errors(int severity, const char *doing) #define CATCH_SYSCALL 1 #define CATCH_ZERO 2 +/* Given a TLS object and the result of an SSL_* call, use + * SSL_get_error to determine whether an error has occurred, and if so + * which one. Return one of TOR_TLS_{DONE|WANTREAD|WANTWRITE|ERROR}. + * If extra&CATCH_SYSCALL is true, return _TOR_TLS_SYSCALL instead of + * reporting syscall errors. If extra&CATCH_ZERO is true, return + * _TOR_TLS_ZERORETURN instead of reporting zero-return errors. + * + * If an error has occurred, log it at level 'severity' and describe the + * current action as 'doing.' + */ static int tor_tls_get_error(tor_tls *tls, int r, int extra, const char *doing, int severity) @@ -97,8 +116,13 @@ tor_tls_get_error(tor_tls *tls, int r, int extra, case SSL_ERROR_SYSCALL: if (extra&CATCH_SYSCALL) return _TOR_TLS_SYSCALL; - log(severity, "TLS error: <syscall error> (errno=%d: %s)",errno, - strerror(errno)); + if (r == 0) + log(severity, "TLS error: unexpected close while %s", doing); + else { + int e = tor_socket_errno(tls->socket); + log(severity, "TLS error: <syscall error while %s> (errno=%d: %s)", + doing, e, strerror(e)); + } tls_log_errors(severity, doing); return TOR_TLS_ERROR; case SSL_ERROR_ZERO_RETURN: @@ -113,6 +137,8 @@ tor_tls_get_error(tor_tls *tls, int r, int extra, } } +/* Initialize OpenSSL, unless it has already been initialized. + */ static void tor_tls_init() { if (!tls_library_is_initialized) { @@ -124,20 +150,24 @@ tor_tls_init() { } } +/* We need to give OpenSSL a callback to verify certificates. This is + * it: We always accept peer certs and complete the handshake. We + * don't validate them until later. + */ static int always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { - /* We always accept peer certs and complete the handshake. We don't validate - * them until later. */ return 1; } -/* Generate a self-signed certificate with the private key 'rsa' and - * identity key 'identity and commonName 'nickname'. Return a certificate - * on success, NULL on failure. - * DOCDOC +/* Generate and sign an X509 certificate with the public key 'rsa', + * signed by the private key 'rsa_sign'. The commonName of the + * certificate will be 'cname'; the commonName of the issuer will be + * cname_sign. The cert will be valid for cert_lifetime seconds + * starting from now. Return a certificate on success, NULL on + * failure. */ -X509 * +static X509 * tor_tls_create_certificate(crypto_pk_env_t *rsa, crypto_pk_env_t *rsa_sign, const char *cname, @@ -236,7 +266,13 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, /* Create a new TLS context. If we are going to be using it as a * server, it must have isServer set to true, 'identity' set to the * identity key used to sign that certificate, and 'nickname' set to - * the server's nickname. Return -1 if failure, else 0. + * the server's nickname. If we're only going to be a client, + * isServer should be false, identity should be NULL, and nickname + * should be NULL. Return -1 if failure, else 0. + * + * You can call this function multiple times. Each time you call it, + * it generates new certificates; all new connections will be begin + * with the new SSL context. */ int tor_tls_context_new(crypto_pk_env_t *identity, @@ -254,12 +290,15 @@ tor_tls_context_new(crypto_pk_env_t *identity, tor_tls_init(); if (isServer) { + /* Generate short-term RSA key. */ if (!(rsa = crypto_new_pk_env())) goto error; if (crypto_pk_generate_key(rsa)<0) goto error; + /* Create certificate signed by identity key. */ cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, key_lifetime); + /* Create self-signed certificate for identity key. */ idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, IDENTITY_CERT_LIFETIME); if (!cert || !idcert) { @@ -334,7 +373,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, return -1; } -/* Create a new TLS object from a TLS context, a filedescriptor, and +/* Create a new TLS object from a TLS context, a file descriptor, and * a flag to determine whether it is functioning as a server. */ tor_tls * @@ -515,6 +554,9 @@ tor_tls_peer_has_cert(tor_tls *tls) return 1; } +/* Return the nickname (if any) that the peer connected on 'tls' + * claims to have. + */ int tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen) { @@ -593,7 +635,7 @@ tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key) if (id_pkey) EVP_PKEY_free(id_pkey); - /* XXXX */ + /* XXXX This should never get invoked, but let's make sure for now. */ tls_log_errors(LOG_WARN, "finishing tor_tls_verify"); return r; @@ -619,12 +661,15 @@ unsigned long tor_tls_get_n_bytes_read(tor_tls *tls) tor_assert(tls); return BIO_number_read(SSL_get_rbio(tls->ssl)); } +/* Return the number of bytes written across the underlying socket. */ unsigned long tor_tls_get_n_bytes_written(tor_tls *tls) { tor_assert(tls); return BIO_number_written(SSL_get_wbio(tls->ssl)); } +/* Implement assert_no_tls_errors: If there are any pending OpenSSL + * errors, log an error message and assert(0). */ void _assert_no_tls_errors(const char *fname, int line) { if (ERR_peek_error() == 0) @@ -636,7 +681,6 @@ void _assert_no_tls_errors(const char *fname, int line) tor_assert(0); } - /* Local Variables: mode:c diff --git a/src/common/tortls.h b/src/common/tortls.h index f0685e6599..b69e951bbe 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -7,16 +7,16 @@ #include "../common/crypto.h" -typedef struct tor_tls_context_st tor_tls_context; +/* Opaque structure to hold a TLS connection. */ typedef struct tor_tls_st tor_tls; +/* Possible return values for most tor_tls_* functions. */ #define TOR_TLS_ERROR -4 #define TOR_TLS_CLOSE -3 #define TOR_TLS_WANTREAD -2 #define TOR_TLS_WANTWRITE -1 #define TOR_TLS_DONE 0 -/* X509* tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname); */ int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer, const char *nickname, unsigned int key_lifetime); tor_tls *tor_tls_new(int sock, int isServer); @@ -33,6 +33,8 @@ int tor_tls_get_pending_bytes(tor_tls *tls); unsigned long tor_tls_get_n_bytes_read(tor_tls *tls); unsigned long tor_tls_get_n_bytes_written(tor_tls *tls); +/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. + */ #define assert_no_tls_errors() _assert_no_tls_errors(__FILE__,__LINE__) void _assert_no_tls_errors(const char *fname, int line); diff --git a/src/common/util.c b/src/common/util.c index 333344959a..7fd01edadb 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2,6 +2,11 @@ /* See LICENSE for licensing information */ /* $Id$ */ +/***** + * util.c: Common functions for strings, IO, network, data structures, + * process control, and cross-platform portability. + *****/ + #include "orconfig.h" #ifdef MS_WINDOWS @@ -86,7 +91,7 @@ #define INADDR_NONE ((unsigned long) -1) #endif -/* in-line the strl functions */ +/* Inline the strl functions if the plaform doesn't have them. */ #ifndef HAVE_STRLCPY #include "strlcpy.c" #endif @@ -94,10 +99,14 @@ #include "strlcat.c" #endif -/* +/***** * Memory wrappers - */ + *****/ +/* Allocate a chunk of 'size' bytes of memory, and return a pointer to + * result. On error, log and terminate the process. (Same as malloc(size), + * but never returns NULL.) + */ void *tor_malloc(size_t size) { void *result; @@ -115,12 +124,20 @@ void *tor_malloc(size_t size) { return result; } +/* Allocate a chunk of 'size' bytes of memory, fill the memory with + * zero bytes, and return a pointer to the result. Log and terminate + * the process on error. (Same as calloc(size,1), but never returns NULL.) + */ void *tor_malloc_zero(size_t size) { void *result = tor_malloc(size); memset(result, 0, size); return result; } +/* Change the size of the memory block pointed to by 'ptr' to 'size' + * bytes long; return the new memory block. On error, log and + * terminate. (Like realloc(ptr,size), but never returns NULL.) + */ void *tor_realloc(void *ptr, size_t size) { void *result; @@ -132,6 +149,10 @@ void *tor_realloc(void *ptr, size_t size) { return result; } +/* Return a newly allocated copy of the NUL-terminated string s. On + * error, log and terminate. (Like strdup(s), but never returns + * NULL.) + */ char *tor_strdup(const char *s) { char *dup; tor_assert(s); @@ -144,6 +165,11 @@ char *tor_strdup(const char *s) { return dup; } +/* Allocate and return a new string containing the first 'n' + * characters of 's'. If 's' is longer than 'n' characters, only the + * first 'n' are copied. The result is always NUL-terminated. (Like + * strndup(s,n), but never returns NULL.) + */ char *tor_strndup(const char *s, size_t n) { char *dup; tor_assert(s); @@ -153,7 +179,8 @@ char *tor_strndup(const char *s, size_t n) { return dup; } -/* Convert s to lowercase. */ +/* Convert all alphabetic characters in the nul-terminated string 's' to + * lowercase. */ void tor_strlower(char *s) { while (*s) { @@ -185,6 +212,10 @@ void set_uint32(char *cp, uint32_t v) } #endif +/* Encode the first 'fromlen' bytes stored at 'from' in hexidecimal; + * write the result as a NUL-terminated string to 'to'. 'to' must + * have at least (2*fromlen)+1 bytes of free space. + */ void hex_encode(const char *from, int fromlen, char *to) { const unsigned char *fp = from; @@ -198,6 +229,11 @@ void hex_encode(const char *from, int fromlen, char *to) *to = '\0'; } +/* Return a pointer to a NUL-terminated hexidecimal string encoding + * the first 'fromlen' bytes of 'from'. (fromlen must be <= 32.) The + * result does not need to be deallocated, but repeated calls to + * hex_str will trash old results. + */ const char *hex_str(const char *from, int fromlen) { static char buf[65]; @@ -207,21 +243,27 @@ const char *hex_str(const char *from, int fromlen) return buf; } -/* - * A simple smartlist interface to make an unordered list of acceptable - * nodes and then choose a random one. - * smartlist_create() mallocs the list, _free() frees the list, - * _add() adds an element, _remove() removes an element if it's there, - * _choose() returns a random element. +/***** + * smartlist_t: a simple resizeable array abstraction. + *****/ + +/* All newly allocated smartlists have this capacity. */ #define SMARTLIST_DEFAULT_CAPACITY 32 + struct smartlist_t { + /* 'list' has enough capacity to store exactly 'capacity' elements + * before it needs to be resized. Only the first 'num_used' (<= + * capacity) elements point to valid data. + */ void **list; int num_used; int capacity; }; +/* Allocate and return an empty smartlist. + */ smartlist_t *smartlist_create() { smartlist_t *sl = tor_malloc(sizeof(smartlist_t)); sl->num_used = 0; @@ -230,32 +272,46 @@ smartlist_t *smartlist_create() { return sl; } +/* Deallocate a smartlist. Does not release storage associated with the + * list's elements. + */ void smartlist_free(smartlist_t *sl) { free(sl->list); free(sl); } +/* Change the capacity of the smartlist to 'n', so that we can grow + * the list upt to'n' elements with no further reallocation or wasted + * space. If 'n' is less than or equal to the number of elements + * currently in the list, reduces the list's capacity as much as + * possible without losing elements. + */ void smartlist_set_capacity(smartlist_t *sl, int n) { - if (n<0) + if (n < sl->num_used) n = sl->num_used; - if (sl->capacity != n && sl->num_used < n) { + if (sl->capacity != n) { sl->capacity = n; sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity); } } -/* Remove all elements from the list. */ +/* Remove all elements from the list. + */ void smartlist_clear(smartlist_t *sl) { sl->num_used = 0; } +/* Set the list's new length to 'len' (which must be <= the list's + * current size). Remove the last smartlist_len(sl)-len elements from the + * list. + */ void smartlist_truncate(smartlist_t *sl, int len) { tor_assert(len <= sl->num_used); sl->num_used = len; } -/* add element to the list */ +/* Append element to the end of the list. */ void smartlist_add(smartlist_t *sl, void *element) { if (sl->num_used >= sl->capacity) { sl->capacity *= 2; @@ -264,12 +320,15 @@ void smartlist_add(smartlist_t *sl, void *element) { sl->list[sl->num_used++] = element; } -/* Add all elements from S2 to S1. */ +/* Append each elements from S2 to the end of S1. */ void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2) { SMARTLIST_FOREACH(s2, void *, element, smartlist_add(sl, element)); } +/* Remove all elements E from sl such that E==element. Does not preserve + * the order of s1. + */ void smartlist_remove(smartlist_t *sl, void *element) { int i; if(element == NULL) @@ -281,6 +340,8 @@ void smartlist_remove(smartlist_t *sl, void *element) { } } +/* Return true iff some element E of sl has E==element. + */ int smartlist_isin(const smartlist_t *sl, void *element) { int i; for(i=0; i < sl->num_used; i++) @@ -289,6 +350,8 @@ int smartlist_isin(const smartlist_t *sl, void *element) { return 0; } +/* Return true iff some element E of sl2 has smartlist_isin(sl1,E). + */ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) { int i; for(i=0; i < sl2->num_used; i++) @@ -297,7 +360,9 @@ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) { return 0; } -/* remove elements of sl1 that aren't in sl2 */ +/* Remove every element E of sl1 such that !smartlist_isin(sl2,E). + * Does not preserve the order of sl1. + */ void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) { int i; for(i=0; i < sl1->num_used; i++) @@ -307,24 +372,33 @@ void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) { } } -/* remove all elements of sl2 from sl1 */ +/* Remove every element E of sl1 such that smartlist_isin(sl2,E). + * Does not preserve the order of sl1. + */ void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) { int i; for(i=0; i < sl2->num_used; i++) smartlist_remove(sl1, sl2->list[i]); } +/* Return a randomly chosen element of sl; or NULL if sl is empty. + */ void *smartlist_choose(const smartlist_t *sl) { if(sl->num_used) return sl->list[crypto_pseudo_rand_int(sl->num_used)]; return NULL; /* no elements to choose from */ } +/* Return the 'idx'th element of sl. + */ void *smartlist_get(const smartlist_t *sl, int idx) { tor_assert(sl && idx>=0 && idx < sl->num_used); return sl->list[idx]; } +/* Change the value of the 'idx'th element of sl to 'val'; return the old + * value of the 'idx'th element. + */ void *smartlist_set(smartlist_t *sl, int idx, void *val) { void *old; @@ -333,6 +407,10 @@ void *smartlist_set(smartlist_t *sl, int idx, void *val) sl->list[idx] = val; return old; } +/* Remove the 'idx'th element of sl; if idx is not the last element, + * swap the last element of sl into the 'idx'th space. Return the old value + * of the 'idx'th element. + */ void *smartlist_del(smartlist_t *sl, int idx) { void *old; @@ -341,6 +419,10 @@ void *smartlist_del(smartlist_t *sl, int idx) sl->list[idx] = sl->list[--sl->num_used]; return old; } +/* Remove the 'idx'th element of sl; if idx is not the last element, + * moving all subsequent elements back one space. Return the old value + * of the 'idx'th element. + */ void *smartlist_del_keeporder(smartlist_t *sl, int idx) { void *old; @@ -351,10 +433,15 @@ void *smartlist_del_keeporder(smartlist_t *sl, int idx) memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx)); return old; } +/* Return the number of items in sl. + */ int smartlist_len(const smartlist_t *sl) { return sl->num_used; } +/* Insert the value 'val' as the new 'idx'th element of 'sl', moving all + * items previously at 'idx' or later forward on space. + */ void smartlist_insert(smartlist_t *sl, int idx, void *val) { tor_assert(sl && idx >= 0 && idx <= sl->num_used); @@ -375,9 +462,9 @@ void smartlist_insert(smartlist_t *sl, int idx, void *val) } } -/* +/***** * Splay-tree implementation of string-to-void* map - */ + *****/ struct strmap_entry_t { SPLAY_ENTRY(strmap_entry_t) node; char *key; @@ -636,7 +723,8 @@ void strmap_free(strmap_t *map, void (*free_val)(void*)) * String manipulation */ -/* return the first char of s that is not whitespace and not a comment */ +/* Return a pointer to the first char of s that is not whitespace and + * not a comment. */ const char *eat_whitespace(const char *s) { tor_assert(s); @@ -653,13 +741,14 @@ const char *eat_whitespace(const char *s) { return s; } +/* Return a pointer to the first char of s that is not a space or a tab. */ const char *eat_whitespace_no_nl(const char *s) { while(*s == ' ' || *s == '\t') ++s; return s; } -/* return the first char of s that is whitespace or '#' or '\0 */ +/* Return a pointer to the first char of s that is whitespace or '#' or '\0 */ const char *find_whitespace(const char *s) { tor_assert(s); @@ -669,10 +758,13 @@ const char *find_whitespace(const char *s) { return s; } -/* - * Time - */ +/***** + * Time + *****/ +/* Set *timeval to the current time of day. On error, log and terminate. + * (Same as gettimeofday(timeval,NULL), but never returns -1.) + */ void tor_gettimeofday(struct timeval *timeval) { #ifdef HAVE_GETTIMEOFDAY if (gettimeofday(timeval, NULL)) { @@ -689,6 +781,8 @@ void tor_gettimeofday(struct timeval *timeval) { return; } +/* Returns the number of microseconds elapsed between *start and *end. + */ long tv_udiff(struct timeval *start, struct timeval *end) { @@ -709,6 +803,8 @@ tv_udiff(struct timeval *start, struct timeval *end) return udiff; } +/* Return -1 if *a<*b, 0 if *a==*b, and 1 if *a>*b. + */ int tv_cmp(struct timeval *a, struct timeval *b) { if (a->tv_sec > b->tv_sec) return 1; @@ -721,12 +817,16 @@ int tv_cmp(struct timeval *a, struct timeval *b) { return 0; } +/* Increment *a by the number of seconds and microseconds in *b. + */ void tv_add(struct timeval *a, struct timeval *b) { a->tv_usec += b->tv_usec; a->tv_sec += b->tv_sec + (a->tv_usec / 1000000); a->tv_usec %= 1000000; } +/* Increment *a by 'ms' milliseconds. + */ void tv_addms(struct timeval *a, long ms) { a->tv_usec += (ms * 1000) % 1000000; a->tv_sec += ((ms * 1000) / 1000000) + (a->tv_usec / 1000000); @@ -743,6 +843,9 @@ static int n_leapdays(int y1, int y2) { static const int days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +/* Return a time_t given a struct tm. The result is given in GMT, and + * does not account for leap seconds. + */ time_t tor_timegm (struct tm *tm) { /* This is a pretty ironclad timegm implementation, snarfed from Python2.2. * It's way more brute-force than fiddling with tzset(). @@ -770,8 +873,10 @@ time_t tor_timegm (struct tm *tm) { * Low-level I/O. */ -/* a wrapper for write(2) that makes sure to write all count bytes. - * Only use if fd is a blocking fd. */ +/* Write 'count' bytes from 'buf' to 'fd'. isSocket must be 1 if fd + * was returned by socket() or accept(), and 0 if fd was returned by + * open(). Return the number of bytes written, or -1 on error. Only + * use if fd is a blocking fd. */ int write_all(int fd, const char *buf, size_t count, int isSocket) { size_t written = 0; int result; @@ -788,8 +893,10 @@ int write_all(int fd, const char *buf, size_t count, int isSocket) { return count; } -/* a wrapper for read(2) that makes sure to read all count bytes. - * Only use if fd is a blocking fd. */ +/* Read 'count' bytes from 'fd' to 'buf'. isSocket must be 1 if fd + * was returned by socket() or accept(), and 0 if fd was returned by + * open(). Return the number of bytes read, or -1 on error. Only use + * if fd is a blocking fd. */ int read_all(int fd, char *buf, size_t count, int isSocket) { size_t numread = 0; int result; @@ -806,6 +913,8 @@ int read_all(int fd, char *buf, size_t count, int isSocket) { return count; } +/* Turn 'socket' into a nonblocking socket. + */ void set_socket_nonblocking(int socket) { #ifdef MS_WINDOWS @@ -850,6 +959,8 @@ int spawn_func(int (*func)(void *), void *data) #endif } +/* End the current thread/process. + */ void spawn_exit() { #ifdef MS_WINDOWS @@ -860,9 +971,16 @@ void spawn_exit() } -/* - * Windows compatibility. - */ +/** + * Allocate a pair of connected sockets. (Like socketpair(family, + * type,protocol,fd), but works on systems that don't have + * socketpair.) + * + * Currently, only (AF_UNIX, SOCK_STREAM, 0 ) sockets are supported. + * Note that on systems without socketpair, this call will sometimes + * fail if localhost is inaccessible (for example, if the networking + * stack is down). + **/ int tor_socketpair(int family, int type, int protocol, int fd[2]) { @@ -966,16 +1084,22 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) #endif } +/* On Windows, WSAEWOULDBLOCK is not always correct: when you see it, + * you need to ask the socket for its actual errno. Also, you need to + * get your errors from WSAGetLastError, not errno. + */ #ifdef MS_WINDOWS -int correct_socket_errno(int s) +int tor_socket_errno(int sock) { int optval, optvallen=sizeof(optval); - tor_assert(errno == WSAEWOULDBLOCK); - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen)) - return errno; - if (optval) - return optval; - return WSAEWOULDBLOCK; + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK && sock >= 0) { + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen)) + return err; + if (optval) + return optval; + } + return err; } #endif @@ -1003,8 +1127,9 @@ file_status_t file_status(const char *fname) return FN_ERROR; } -/* Check whether dirname exists and is private. If yes returns - 0. Else returns -1. */ +/* Check whether dirname exists and is private. If yes returns 0. If + * it does not exist, and create is set, try to creat it and return 0 + * on success. Else return -1. */ int check_private_dir(const char *dirname, int create) { int r; @@ -1056,6 +1181,11 @@ int check_private_dir(const char *dirname, int create) return 0; } +/* Create a file named 'fname' with the contents 'str'. Overwrite the + * previous 'fname' if possible. Return 0 on success, -1 on failure. + * + * This function replaces the old file atomically, if possible. + */ int write_str_to_file(const char *fname, const char *str) { @@ -1084,6 +1214,7 @@ write_str_to_file(const char *fname, const char *str) return -1; } fclose(file); + /* XXXX This won't work on windows: you can't use rename to replace a file.*/ if (rename(tempname, fname)) { log(LOG_WARN, "Error replacing %s: %s", fname, strerror(errno)); return -1; @@ -1091,6 +1222,9 @@ write_str_to_file(const char *fname, const char *str) return 0; } +/* Read the contents of 'filename' into a newly allocated string; return the + * string on success or NULL on failure. + */ char *read_file_to_str(const char *filename) { int fd; /* router file */ struct stat statbuf; @@ -1181,6 +1315,9 @@ try_next_line: return 1; } +/* Return true iff 'ip' (in host order) is an IP reserved to localhost, + * or reserved for local networks by RFC 1918. + */ int is_internal_IP(uint32_t ip) { if (((ip & 0xff000000) == 0x0a000000) || /* 10/8 */ @@ -1193,9 +1330,13 @@ int is_internal_IP(uint32_t ip) { return 0; } +/* Hold the result of our call to 'uname'. */ static char uname_result[256]; +/* True iff uname_Result is set. */ static int uname_result_is_set = 0; +/* Return a pointer to a description of our platform. + */ const char * get_uname(void) { @@ -1224,6 +1365,10 @@ get_uname(void) static int start_daemon_called = 0; static int finish_daemon_called = 0; static int daemon_filedes[2]; +/* Begin running this process as a daemon. The child process will return + * quickly; the parent process will wait around until the child process calls + * finish_daemon. + */ void start_daemon(char *desired_cwd) { pid_t pid; @@ -1278,6 +1423,9 @@ void start_daemon(char *desired_cwd) } } +/* Tell the parent process that the child has successfully finished setup, + * and the daemon is now running. + */ void finish_daemon(void) { int nullfd; @@ -1313,6 +1461,8 @@ void start_daemon(char *cp) {} void finish_daemon(void) {} #endif +/* Write the current process ID, followed by NL, into 'filaname', + */ void write_pidfile(char *filename) { #ifndef MS_WINDOWS FILE *pidfile; @@ -1327,6 +1477,9 @@ void write_pidfile(char *filename) { #endif } +/* Call setuid and setgid to run as 'user':'group'. Return 0 on + * success. On failure, log and return -1. + */ int switch_id(char *user, char *group) { #ifndef MS_WINDOWS struct passwd *pw = NULL; @@ -1377,6 +1530,10 @@ int switch_id(char *user, char *group) { return -1; } +/* Set *addr to the IP address (in dotted-quad notation) stored in c. + * Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr), + * but works on Windows.) + */ int tor_inet_aton(const char *c, struct in_addr* addr) { #ifdef HAVE_INET_ATON diff --git a/src/common/util.h b/src/common/util.h index 6ef0484803..708c87fd28 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -32,9 +32,10 @@ #endif #ifdef MS_WINDOWS -/* Windows names string functions funnily. */ +/* Windows names string functions differently from most other platforms. */ #define strncasecmp strnicmp #define strcasecmp stricmp +/* "inline" is __inline on windows. " */ #define INLINE __inline /* Windows compilers before VC7 don't have __FUNCTION__. */ #if _MSC_VER < 1300 @@ -44,6 +45,9 @@ #define INLINE inline #endif +/* Replace assert() with a variant that sends failures to the log before + * calling assert() normally. + */ #ifdef NDEBUG #define tor_assert(expr) do {} while(0) #else @@ -56,6 +60,12 @@ } } while (0) #endif +/* On windows, you have to call close() on fds returned by open(), and + * closesocket() on fds returned by socket(). On Unix, everything + * gets close()'d. We abstract this difference by always using the + * following macro to close sockets, and always using close() on + * files. + */ #ifdef MS_WINDOWS #define tor_close_socket(s) closesocket(s) #else @@ -63,6 +73,7 @@ #endif /* legal characters in a filename */ +/* XXXX This isn't so on windows. */ #define CONFIG_LEGAL_FILENAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/" size_t strlcat(char *dst, const char *src, size_t siz); @@ -76,6 +87,10 @@ char *tor_strndup(const char *s, size_t n); #define tor_free(p) do {if(p) {free(p); (p)=NULL;}} while(0) void tor_strlower(char *s); +/* Some platforms segfault when you try to access a multi-byte type + * that isn't aligned to a word boundary. The macros and/or functions + * below can be used to access unaligned data on any platform. + */ #ifdef UNALIGNED_INT_ACCESS_OK #define get_uint16(cp) (*(uint16_t*)(cp)) #define get_uint32(cp) (*(uint32_t*)(cp)) @@ -116,6 +131,7 @@ void set_uint32(char *cp, uint32_t v); void hex_encode(const char *from, int fromlen, char *to); const char *hex_str(const char *from, int fromlen); +/* Resizeable array. */ typedef struct smartlist_t smartlist_t; smartlist_t *smartlist_create(); @@ -168,10 +184,12 @@ void strmap_iter_get(strmap_iter_t *iter, const char **keyp, void **valp); int strmap_iter_done(strmap_iter_t *iter); +/* String manipulation */ const char *eat_whitespace(const char *s); const char *eat_whitespace_no_nl(const char *s); const char *find_whitespace(const char *s); +/* Time helpers */ void tor_gettimeofday(struct timeval *timeval); long tv_udiff(struct timeval *start, struct timeval *end); void tv_addms(struct timeval *a, long ms); @@ -221,19 +239,22 @@ struct in_addr; int tor_inet_aton(const char *cp, struct in_addr *addr); int tor_lookup_hostname(const char *name, uint32_t *addr); -/* For stupid historical reasons, windows sockets have an independent set of - * errnos which they use as the fancy strikes them. +/* For stupid historical reasons, windows sockets have an independent + * set of errnos, and an independent way to get them. Also, you can't + * always believe WSAEWOULDBLOCK. Use the macros below to compare + * errnos against expected values, and use tor_socket_errno to find + * the actual errno after a socket operation fails. */ #ifdef MS_WINDOWS -#define ERRNO_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK) -#define ERRNO_EINPROGRESS(e) ((e) == WSAEINPROGRESS) -#define ERRNO_CONN_EINPROGRESS(e) ((e) == WSAEINPROGRESS || (e) == WSAEINVAL) -int correct_socket_errno(int s); +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK) +#define ERRNO_IS_EINPROGRESS(e) ((e) == WSAEINPROGRESS) +#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == WSAEINPROGRESS || (e)== WSAEINVAL) +int tor_socket_errno(int sock); #else -#define ERRNO_EAGAIN(e) ((e) == EAGAIN) -#define ERRNO_EINPROGRESS(e) ((e) == EINPROGRESS) -#define ERRNO_CONN_EINPROGRESS(e) ((e) == EINPROGRESS) -#define correct_socket_errno(s) (errno) +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN) +#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS) +#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS) +#define tor_socket_errno(sock) (errno) #endif #endif diff --git a/src/or/buffers.c b/src/or/buffers.c index 6598c2654c..931a83b0ff 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -190,15 +190,9 @@ int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof) { // log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most); read_result = recv(s, buf->mem+buf->datalen, at_most, 0); if (read_result < 0) { - if(!ERRNO_EAGAIN(errno)) { /* it's a real error */ + if(!ERRNO_IS_EAGAIN(tor_socket_errno(s))) { /* it's a real error */ return -1; } -#ifdef MS_WINDOWS - e = correct_socket_errno(s); - if(!ERRNO_EAGAIN(e)) { /* no, it *is* a real error! */ - return -1; - } -#endif return 0; } else if (read_result == 0) { log_fn(LOG_DEBUG,"Encountered eof"); @@ -262,16 +256,11 @@ int flush_buf(int s, buf_t *buf, int *buf_flushlen) write_result = send(s, buf->mem, *buf_flushlen, 0); if (write_result < 0) { - if(!ERRNO_EAGAIN(errno)) { /* it's a real error */ - tor_assert(errno != EPIPE); /* get a stack trace to find epipe bugs */ + if(!ERRNO_IS_EAGAIN(tor_socket_errno(s))) { /* it's a real error */ + /* get a stack trace to find epipe bugs */ + tor_assert(tor_socket_errno(s) != EPIPE); return -1; } -#ifdef MS_WINDOWS - e = correct_socket_errno(s); - if(!ERRNO_EAGAIN(e)) { /* no, it *is* a real error! */ - return -1; - } -#endif log_fn(LOG_DEBUG,"write() would block, returning."); return 0; } else { diff --git a/src/or/connection.c b/src/or/connection.c index 1b1f4c4b15..690f442618 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -278,12 +278,14 @@ int connection_create_listener(char *bindaddress, uint16_t bindport, int type) { setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one)); if(bind(s,(struct sockaddr *)&bindaddr,sizeof(bindaddr)) < 0) { - log_fn(LOG_WARN,"Could not bind to port %u: %s",bindport,strerror(errno)); + log_fn(LOG_WARN,"Could not bind to port %u: %s",bindport, + strerror(tor_socket_errno())); return -1; } if(listen(s,SOMAXCONN) < 0) { - log_fn(LOG_WARN,"Could not listen on port %u: %s",bindport,strerror(errno)); + log_fn(LOG_WARN,"Could not listen on port %u: %s",bindport, + strerror(tor_socket_errno())); return -1; } @@ -317,14 +319,8 @@ static int connection_handle_listener_read(connection_t *conn, int new_type) { news = accept(conn->s,(struct sockaddr *)&remote,&remotelen); if (news == -1) { /* accept() error */ - if(ERRNO_EAGAIN(errno)) { -#ifdef MS_WINDOWS - e = correct_socket_errno(conn->s); - if (ERRNO_EAGAIN(e)) - return 0; -#else + if(ERRNO_IS_EAGAIN(tor_socket_errno(conn->s))) { return 0; /* he hung up before we could accept(). that's fine. */ -#endif } /* else there was a real error. */ log_fn(LOG_WARN,"accept() failed. Closing listener."); @@ -396,9 +392,10 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_ log_fn(LOG_DEBUG,"Connecting to %s:%u.",address,port); if(connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) { - if(!ERRNO_CONN_EINPROGRESS(errno)) { + if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(s))) { /* yuck. kill it. */ - log_fn(LOG_INFO,"Connect() to %s:%u failed: %s",address,port,strerror(errno)); + log_fn(LOG_INFO,"Connect() to %s:%u failed: %s",address,port, + strerror(tor_socket_errno(s))); tor_close_socket(s); return -1; } else { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 365b39ad97..7a9bdfd0a3 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -479,7 +479,7 @@ int connection_edge_finished_flushing(connection_t *conn) { switch(conn->state) { case EXIT_CONN_STATE_CONNECTING: if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */ - if(!ERRNO_CONN_EINPROGRESS(errno)) { + if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(conn->s))) { /* yuck. kill it. */ log_fn(LOG_DEBUG,"in-progress exit connect failed. Removing."); connection_mark_for_close(conn, END_STREAM_REASON_CONNECTFAILED); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index bb6eb1367e..02ee368a01 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -49,7 +49,7 @@ int connection_or_finished_flushing(connection_t *conn) { switch(conn->state) { case OR_CONN_STATE_CONNECTING: if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */ - if(!ERRNO_CONN_EINPROGRESS(errno)){ + if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(conn->s))) { log_fn(LOG_DEBUG,"in-progress connect failed. Removing."); connection_mark_for_close(conn,0); return -1; diff --git a/src/or/directory.c b/src/or/directory.c index 1c8fa059a0..9c6722390a 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -480,7 +480,7 @@ int connection_dir_finished_flushing(connection_t *conn) { switch(conn->state) { case DIR_CONN_STATE_CONNECTING: if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */ - if(!ERRNO_CONN_EINPROGRESS(errno)) { + if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(conn->s))) { log_fn(LOG_DEBUG,"in-progress connect failed. Removing."); router_mark_as_down(conn->nickname); /* don't try him again */ connection_mark_for_close(conn,0); diff --git a/src/or/main.c b/src/or/main.c index 83dc87dfe8..836f4d665b 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -653,8 +653,10 @@ static int do_main_loop(void) { /* let catch() handle things like ^c, and otherwise don't worry about it */ if(poll_result < 0) { - if(errno != EINTR) { /* let the program survive things like ^z */ - log_fn(LOG_ERR,"poll failed: %s",strerror(errno)); + /* let the program survive things like ^z */ + if(tor_socket_errno(-1) != EINTR) { + log_fn(LOG_ERR,"poll failed: %s [%d]", + strerror(tor_socket_errno(-1)), tor_socket_errno(-1)); return -1; } else { log_fn(LOG_DEBUG,"poll interrupted."); diff --git a/src/or/test.c b/src/or/test.c index 536511949d..6e37ba1435 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -205,29 +205,29 @@ void test_crypto_dh() { crypto_dh_env_t *dh1, *dh2; - char p1[CRYPTO_DH_SIZE]; - char p2[CRYPTO_DH_SIZE]; - char s1[CRYPTO_DH_SIZE]; - char s2[CRYPTO_DH_SIZE]; + char p1[DH_BYTES]; + char p2[DH_BYTES]; + char s1[DH_BYTES]; + char s2[DH_BYTES]; int s1len, s2len; dh1 = crypto_dh_new(); dh2 = crypto_dh_new(); - test_eq(crypto_dh_get_bytes(dh1), CRYPTO_DH_SIZE); - test_eq(crypto_dh_get_bytes(dh2), CRYPTO_DH_SIZE); - - memset(p1, 0, CRYPTO_DH_SIZE); - memset(p2, 0, CRYPTO_DH_SIZE); - test_memeq(p1, p2, CRYPTO_DH_SIZE); - test_assert(! crypto_dh_get_public(dh1, p1, CRYPTO_DH_SIZE)); - test_memneq(p1, p2, CRYPTO_DH_SIZE); - test_assert(! crypto_dh_get_public(dh2, p2, CRYPTO_DH_SIZE)); - test_memneq(p1, p2, CRYPTO_DH_SIZE); - - memset(s1, 0, CRYPTO_DH_SIZE); - memset(s2, 0xFF, CRYPTO_DH_SIZE); - s1len = crypto_dh_compute_secret(dh1, p2, CRYPTO_DH_SIZE, s1, 50); - s2len = crypto_dh_compute_secret(dh2, p1, CRYPTO_DH_SIZE, s2, 50); + test_eq(crypto_dh_get_bytes(dh1), DH_BYTES); + test_eq(crypto_dh_get_bytes(dh2), DH_BYTES); + + memset(p1, 0, DH_BYTES); + memset(p2, 0, DH_BYTES); + test_memeq(p1, p2, DH_BYTES); + test_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); + test_memneq(p1, p2, DH_BYTES); + test_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); + test_memneq(p1, p2, DH_BYTES); + + memset(s1, 0, DH_BYTES); + memset(s2, 0xFF, DH_BYTES); + s1len = crypto_dh_compute_secret(dh1, p2, DH_BYTES, s1, 50); + s2len = crypto_dh_compute_secret(dh2, p1, DH_BYTES, s2, 50); test_assert(s1len > 0); test_eq(s1len, s2len); test_memeq(s1, s2, s1len); |