|
@@ -128,132 +128,6 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
|
|
|
#include "lib/net/address.h"
|
|
|
#include "lib/sandbox/sandbox.h"
|
|
|
|
|
|
-
|
|
|
- * tell Tor it's allowed to use. */
|
|
|
-#define ULIMIT_BUFFER 32
|
|
|
-
|
|
|
-
|
|
|
- * system we want to use up to that number. (Some systems have a low soft
|
|
|
- * limit, and let us set it higher.) We compute this by finding the largest
|
|
|
- * number that we can use.
|
|
|
- *
|
|
|
- * If the limit is below the reserved file descriptor value (ULIMIT_BUFFER),
|
|
|
- * return -1 and <b>max_out</b> is untouched.
|
|
|
- *
|
|
|
- * If we can't find a number greater than or equal to <b>limit</b>, then we
|
|
|
- * fail by returning -1 and <b>max_out</b> is untouched.
|
|
|
- *
|
|
|
- * If we are unable to set the limit value because of setrlimit() failing,
|
|
|
- * return 0 and <b>max_out</b> is set to the current maximum value returned
|
|
|
- * by getrlimit().
|
|
|
- *
|
|
|
- * Otherwise, return 0 and store the maximum we found inside <b>max_out</b>
|
|
|
- * and set <b>max_sockets</b> with that value as well.*/
|
|
|
-int
|
|
|
-set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
-{
|
|
|
- if (limit < ULIMIT_BUFFER) {
|
|
|
- log_warn(LD_CONFIG,
|
|
|
- "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * automatically determine a limit. Re Cygwin, see
|
|
|
- * http:
|
|
|
- * For an iPhone, 9999 should work. For Windows and all other unknown
|
|
|
- * systems we use 15000 as the default. */
|
|
|
-#ifndef HAVE_GETRLIMIT
|
|
|
-#if defined(CYGWIN) || defined(__CYGWIN__)
|
|
|
- const char *platform = "Cygwin";
|
|
|
- const unsigned long MAX_CONNECTIONS = 3200;
|
|
|
-#elif defined(_WIN32)
|
|
|
- const char *platform = "Windows";
|
|
|
- const unsigned long MAX_CONNECTIONS = 15000;
|
|
|
-#else
|
|
|
- const char *platform = "unknown platforms with no getrlimit()";
|
|
|
- const unsigned long MAX_CONNECTIONS = 15000;
|
|
|
-#endif
|
|
|
- log_fn(LOG_INFO, LD_NET,
|
|
|
- "This platform is missing getrlimit(). Proceeding.");
|
|
|
- if (limit > MAX_CONNECTIONS) {
|
|
|
- log_warn(LD_CONFIG,
|
|
|
- "We do not support more than %lu file descriptors "
|
|
|
- "on %s. Tried to raise to %lu.",
|
|
|
- (unsigned long)MAX_CONNECTIONS, platform, (unsigned long)limit);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- limit = MAX_CONNECTIONS;
|
|
|
-#else
|
|
|
- struct rlimit rlim;
|
|
|
-
|
|
|
- if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
|
|
|
- log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
|
|
|
- strerror(errno));
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (rlim.rlim_max < limit) {
|
|
|
- log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
|
|
|
- "limited to %lu. Please change your ulimit -n.",
|
|
|
- (unsigned long)limit, (unsigned long)rlim.rlim_max);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (rlim.rlim_max > rlim.rlim_cur) {
|
|
|
- log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
|
|
|
- (unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
|
|
|
- }
|
|
|
-
|
|
|
- * max fails at least we'll have a valid value of maximum sockets. */
|
|
|
- *max_out = (int)rlim.rlim_cur - ULIMIT_BUFFER;
|
|
|
- set_max_sockets(*max_out);
|
|
|
- rlim.rlim_cur = rlim.rlim_max;
|
|
|
-
|
|
|
- if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
|
|
|
- int couldnt_set = 1;
|
|
|
- const int setrlimit_errno = errno;
|
|
|
-#ifdef OPEN_MAX
|
|
|
- uint64_t try_limit = OPEN_MAX - ULIMIT_BUFFER;
|
|
|
- if (errno == EINVAL && try_limit < (uint64_t) rlim.rlim_cur) {
|
|
|
-
|
|
|
- * full of nasty lies. I'm looking at you, OSX 10.5.... */
|
|
|
- rlim.rlim_cur = MIN((rlim_t) try_limit, rlim.rlim_cur);
|
|
|
- if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) {
|
|
|
- if (rlim.rlim_cur < (rlim_t)limit) {
|
|
|
- log_warn(LD_CONFIG, "We are limited to %lu file descriptors by "
|
|
|
- "OPEN_MAX (%lu), and ConnLimit is %lu. Changing "
|
|
|
- "ConnLimit; sorry.",
|
|
|
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
|
|
|
- (unsigned long)limit);
|
|
|
- } else {
|
|
|
- log_info(LD_CONFIG, "Dropped connection limit to %lu based on "
|
|
|
- "OPEN_MAX (%lu); Apparently, %lu was too high and rlimit "
|
|
|
- "lied to us.",
|
|
|
- (unsigned long)try_limit, (unsigned long)OPEN_MAX,
|
|
|
- (unsigned long)rlim.rlim_max);
|
|
|
- }
|
|
|
- couldnt_set = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
- if (couldnt_set) {
|
|
|
- log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s",
|
|
|
- strerror(setrlimit_errno));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- limit = rlim.rlim_cur;
|
|
|
-#endif
|
|
|
-
|
|
|
- if (limit > INT_MAX)
|
|
|
- limit = INT_MAX;
|
|
|
- tor_assert(max_out);
|
|
|
- *max_out = (int)limit - ULIMIT_BUFFER;
|
|
|
- set_max_sockets(*max_out);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
static char uname_result[256];
|
|
|
|
|
@@ -351,126 +225,6 @@ get_uname,(void))
|
|
|
* Process control
|
|
|
*/
|
|
|
|
|
|
-#if defined(HW_PHYSMEM64)
|
|
|
-
|
|
|
-#define INT64_HW_MEM HW_PHYSMEM64
|
|
|
-#elif defined(HW_MEMSIZE)
|
|
|
-
|
|
|
-#define INT64_HW_MEM HW_MEMSIZE
|
|
|
-#endif
|
|
|
-
|
|
|
-
|
|
|
- * Helper: try to detect the total system memory, and return it. On failure,
|
|
|
- * return 0.
|
|
|
- */
|
|
|
-static uint64_t
|
|
|
-get_total_system_memory_impl(void)
|
|
|
-{
|
|
|
-#if defined(__linux__)
|
|
|
-
|
|
|
- * shouldn't _want_ to write portable code, I guess? */
|
|
|
- unsigned long long result=0;
|
|
|
- int fd = -1;
|
|
|
- char *s = NULL;
|
|
|
- const char *cp;
|
|
|
- size_t file_size=0;
|
|
|
- if (-1 == (fd = tor_open_cloexec("/proc/meminfo",O_RDONLY,0)))
|
|
|
- return 0;
|
|
|
- s = read_file_to_str_until_eof(fd, 65536, &file_size);
|
|
|
- if (!s)
|
|
|
- goto err;
|
|
|
- cp = strstr(s, "MemTotal:");
|
|
|
- if (!cp)
|
|
|
- goto err;
|
|
|
-
|
|
|
- if (sscanf(cp, "MemTotal: %llu kB\n", &result) != 1)
|
|
|
- goto err;
|
|
|
-
|
|
|
- close(fd);
|
|
|
- tor_free(s);
|
|
|
- return result * 1024;
|
|
|
-
|
|
|
-
|
|
|
- err:
|
|
|
- tor_free(s);
|
|
|
- close(fd);
|
|
|
- return 0;
|
|
|
-
|
|
|
-#elif defined (_WIN32)
|
|
|
-
|
|
|
- MEMORYSTATUSEX ms;
|
|
|
- memset(&ms, 0, sizeof(ms));
|
|
|
- ms.dwLength = sizeof(ms);
|
|
|
- if (! GlobalMemoryStatusEx(&ms))
|
|
|
- return 0;
|
|
|
-
|
|
|
- return ms.ullTotalPhys;
|
|
|
-
|
|
|
-#elif defined(HAVE_SYSCTL) && defined(INT64_HW_MEM)
|
|
|
-
|
|
|
- * variant if we know about it. */
|
|
|
- uint64_t memsize = 0;
|
|
|
- size_t len = sizeof(memsize);
|
|
|
- int mib[2] = {CTL_HW, INT64_HW_MEM};
|
|
|
- if (sysctl(mib,2,&memsize,&len,NULL,0))
|
|
|
- return 0;
|
|
|
-
|
|
|
- return memsize;
|
|
|
-
|
|
|
-#elif defined(HAVE_SYSCTL) && defined(HW_PHYSMEM)
|
|
|
-
|
|
|
- * HW_PHYSMEM. */
|
|
|
- size_t memsize=0;
|
|
|
- size_t len = sizeof(memsize);
|
|
|
- int mib[2] = {CTL_HW, HW_USERMEM};
|
|
|
- if (sysctl(mib,2,&memsize,&len,NULL,0))
|
|
|
- return 0;
|
|
|
-
|
|
|
- return memsize;
|
|
|
-
|
|
|
-#else
|
|
|
-
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * Try to find out how much physical memory the system has. On success,
|
|
|
- * return 0 and set *<b>mem_out</b> to that value. On failure, return -1.
|
|
|
- */
|
|
|
-MOCK_IMPL(int,
|
|
|
-get_total_system_memory, (size_t *mem_out))
|
|
|
-{
|
|
|
- static size_t mem_cached=0;
|
|
|
- uint64_t m = get_total_system_memory_impl();
|
|
|
- if (0 == m) {
|
|
|
-
|
|
|
-
|
|
|
- if (0 == mem_cached) {
|
|
|
-
|
|
|
- *mem_out = 0;
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- *mem_out = mem_cached;
|
|
|
- return 0;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-#if SIZE_MAX != UINT64_MAX
|
|
|
- if (m > SIZE_MAX) {
|
|
|
-
|
|
|
- * system: we could have more system memory than would fit in a
|
|
|
- * size_t. */
|
|
|
- m = SIZE_MAX;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- *mem_out = mem_cached = (size_t) m;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
* bytes of passphrase into <b>output</b>. Return the number of bytes in
|
|
|
* the passphrase, excluding terminating NUL.
|