compat.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /* Copyright 2003-2004 Roger Dingledine; Copyright 2004 Nick Mathewson */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /* This is required on rh7 to make strptime not complain.
  5. */
  6. #define _GNU_SOURCE
  7. #include "orconfig.h"
  8. #include "compat.h"
  9. #ifdef MS_WINDOWS
  10. #include <process.h>
  11. #endif
  12. #ifdef HAVE_UNAME
  13. #include <sys/utsname.h>
  14. #endif
  15. #ifdef HAVE_SYS_TIME_H
  16. #include <sys/time.h>
  17. #endif
  18. #ifdef HAVE_UNISTD_H
  19. #include <unistd.h>
  20. #endif
  21. #ifdef HAVE_SYS_FCNTL_H
  22. #include <sys/fcntl.h>
  23. #endif
  24. #ifdef HAVE_PWD_H
  25. #include <pwd.h>
  26. #endif
  27. #ifdef HAVE_GRP_H
  28. #include <grp.h>
  29. #endif
  30. #ifdef HAVE_FCNTL_H
  31. #include <fcntl.h>
  32. #endif
  33. #ifdef HAVE_SYS_RESOURCE_H
  34. #include <sys/resource.h>
  35. #endif
  36. #ifdef HAVE_ERRNO_H
  37. #include <errno.h>
  38. #endif
  39. #ifdef HAVE_NETINET_IN_H
  40. #include <netinet/in.h>
  41. #endif
  42. #ifdef HAVE_ARPA_INET_H
  43. #include <arpa/inet.h>
  44. #endif
  45. #ifndef HAVE_GETTIMEOFDAY
  46. #ifdef HAVE_FTIME
  47. #include <sys/timeb.h>
  48. #endif
  49. #endif
  50. #ifdef HAVE_SYS_SOCKET_H
  51. #include <sys/socket.h>
  52. #endif
  53. #ifdef HAVE_SYS_PARAM_H
  54. #include <sys/param.h> /* FreeBSD needs this to know what version it is */
  55. #endif
  56. #include <stdarg.h>
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include <string.h>
  60. #include <assert.h>
  61. #include "log.h"
  62. #include "util.h"
  63. /* Inline the strl functions if the platform doesn't have them. */
  64. #ifndef HAVE_STRLCPY
  65. #include "strlcpy.c"
  66. #endif
  67. #ifndef HAVE_STRLCAT
  68. #include "strlcat.c"
  69. #endif
  70. /** Replacement for snprintf. Differs from platform snprintf in two
  71. * ways: First, always NUL-terminates its output. Second, always
  72. * returns -1 if the result is truncated. (Note that this return
  73. * behavior does <i>not</i> conform to C99; it just happens to be the
  74. * easiest to emulate "return -1" with conformant implementations than
  75. * it is to emulate "return number that would be written" with
  76. * non-conformant implementations.) */
  77. int tor_snprintf(char *str, size_t size, const char *format, ...)
  78. {
  79. va_list ap;
  80. int r;
  81. va_start(ap,format);
  82. r = tor_vsnprintf(str,size,format,ap);
  83. va_end(ap);
  84. return r;
  85. }
  86. /** Replacement for vsnpritnf; behavior differs as tor_snprintf differs from
  87. * snprintf.
  88. */
  89. int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
  90. {
  91. int r;
  92. #ifdef MS_WINDOWS
  93. r = _vsnprintf(str, size, format, args);
  94. #else
  95. r = vsnprintf(str, size, format, args);
  96. #endif
  97. str[size-1] = '\0';
  98. if (r < 0 || ((size_t)r) >= size)
  99. return -1;
  100. return r;
  101. }
  102. #ifndef UNALIGNED_INT_ACCESS_OK
  103. /**
  104. * Read a 16-bit value beginning at <b>cp</b>. Equaivalent to
  105. * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
  106. * unaligned memory access.
  107. */
  108. uint16_t get_uint16(const char *cp)
  109. {
  110. uint16_t v;
  111. memcpy(&v,cp,2);
  112. return v;
  113. }
  114. /**
  115. * Read a 32-bit value beginning at <b>cp</b>. Equaivalent to
  116. * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
  117. * unaligned memory access.
  118. */
  119. uint32_t get_uint32(const char *cp)
  120. {
  121. uint32_t v;
  122. memcpy(&v,cp,4);
  123. return v;
  124. }
  125. /**
  126. * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
  127. * *(uint16_t)(cp) = v, but will not cause segfaults on platforms that forbid
  128. * unaligned memory access. */
  129. void set_uint16(char *cp, uint16_t v)
  130. {
  131. memcpy(cp,&v,2);
  132. }
  133. /**
  134. * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
  135. * *(uint32_t)(cp) = v, but will not cause segfaults on platforms that forbid
  136. * unaligned memory access. */
  137. void set_uint32(char *cp, uint32_t v)
  138. {
  139. memcpy(cp,&v,4);
  140. }
  141. #endif
  142. /**
  143. * Rename the file 'from' to the file 'to'. On unix, this is the same as
  144. * rename(2). On windows, this removes 'to' first if it already exists.
  145. * Returns 0 on success. Returns -1 and sets errno on failure.
  146. */
  147. int replace_file(const char *from, const char *to)
  148. {
  149. #ifndef MS_WINDOWS
  150. return rename(from,to);
  151. #else
  152. switch(file_status(to))
  153. {
  154. case FN_NOENT:
  155. break;
  156. case FN_FILE:
  157. if (unlink(to)) return -1;
  158. break;
  159. case FN_ERROR:
  160. return -1;
  161. case FN_DIR:
  162. errno = EISDIR;
  163. return -1;
  164. }
  165. return rename(from,to);
  166. #endif
  167. }
  168. /** Turn <b>socket</b> into a nonblocking socket.
  169. */
  170. void set_socket_nonblocking(int socket)
  171. {
  172. #ifdef MS_WINDOWS
  173. /* Yes means no and no means yes. Do you not want to be nonblocking? */
  174. int nonblocking = 0;
  175. ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
  176. #else
  177. fcntl(socket, F_SETFL, O_NONBLOCK);
  178. #endif
  179. }
  180. /**
  181. * Allocate a pair of connected sockets. (Like socketpair(family,
  182. * type,protocol,fd), but works on systems that don't have
  183. * socketpair.)
  184. *
  185. * Currently, only (AF_UNIX, SOCK_STREAM, 0 ) sockets are supported.
  186. *
  187. * Note that on systems without socketpair, this call will fail if
  188. * localhost is inaccessible (for example, if the networking
  189. * stack is down). And even if it succeeds, the socket pair will not
  190. * be able to read while localhost is down later (the socket pair may
  191. * even close, depending on OS-specific timeouts).
  192. **/
  193. int
  194. tor_socketpair(int family, int type, int protocol, int fd[2])
  195. {
  196. #ifdef HAVE_SOCKETPAIR
  197. return socketpair(family, type, protocol, fd);
  198. #else
  199. /* This socketpair does not work when localhost is down. So
  200. * it's really not the same thing at all. But it's close enough
  201. * for now, and really, when localhost is down sometimes, we
  202. * have other problems too.
  203. */
  204. int listener = -1;
  205. int connector = -1;
  206. int acceptor = -1;
  207. struct sockaddr_in listen_addr;
  208. struct sockaddr_in connect_addr;
  209. int size;
  210. if (protocol
  211. #ifdef AF_UNIX
  212. || family != AF_UNIX
  213. #endif
  214. ) {
  215. #ifdef MS_WINDOWS
  216. errno = WSAEAFNOSUPPORT;
  217. #else
  218. errno = EAFNOSUPPORT;
  219. #endif
  220. return -1;
  221. }
  222. if (!fd) {
  223. errno = EINVAL;
  224. return -1;
  225. }
  226. listener = socket(AF_INET, type, 0);
  227. if (listener == -1)
  228. return -1;
  229. memset (&listen_addr, 0, sizeof (listen_addr));
  230. listen_addr.sin_family = AF_INET;
  231. listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  232. listen_addr.sin_port = 0; /* kernel choses port. */
  233. if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
  234. == -1)
  235. goto tidy_up_and_fail;
  236. if (listen(listener, 1) == -1)
  237. goto tidy_up_and_fail;
  238. connector = socket(AF_INET, type, 0);
  239. if (connector == -1)
  240. goto tidy_up_and_fail;
  241. /* We want to find out the port number to connect to. */
  242. size = sizeof (connect_addr);
  243. if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
  244. goto tidy_up_and_fail;
  245. if (size != sizeof (connect_addr))
  246. goto abort_tidy_up_and_fail;
  247. if (connect(connector, (struct sockaddr *) &connect_addr,
  248. sizeof (connect_addr)) == -1)
  249. goto tidy_up_and_fail;
  250. size = sizeof (listen_addr);
  251. acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
  252. if (acceptor == -1)
  253. goto tidy_up_and_fail;
  254. if (size != sizeof(listen_addr))
  255. goto abort_tidy_up_and_fail;
  256. tor_close_socket(listener);
  257. /* Now check we are talking to ourself by matching port and host on the
  258. two sockets. */
  259. if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
  260. goto tidy_up_and_fail;
  261. if (size != sizeof (connect_addr)
  262. || listen_addr.sin_family != connect_addr.sin_family
  263. || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
  264. || listen_addr.sin_port != connect_addr.sin_port) {
  265. goto abort_tidy_up_and_fail;
  266. }
  267. fd[0] = connector;
  268. fd[1] = acceptor;
  269. return 0;
  270. abort_tidy_up_and_fail:
  271. #ifdef MS_WINDOWS
  272. errno = WSAECONNABORTED;
  273. #else
  274. errno = ECONNABORTED; /* I hope this is portable and appropriate. */
  275. #endif
  276. tidy_up_and_fail:
  277. {
  278. int save_errno = errno;
  279. if (listener != -1)
  280. tor_close_socket(listener);
  281. if (connector != -1)
  282. tor_close_socket(connector);
  283. if (acceptor != -1)
  284. tor_close_socket(acceptor);
  285. errno = save_errno;
  286. return -1;
  287. }
  288. #endif
  289. }
  290. /** Get the maximum allowed number of file descriptors. (Some systems
  291. * have a low soft limit.) Make sure we set it to at least
  292. * <b>required_min</b>. Return 0 if we can, or -1 if we fail. */
  293. int set_max_file_descriptors(unsigned int required_min) {
  294. #ifndef HAVE_GETRLIMIT
  295. log_fn(LOG_INFO,"This platform is missing getrlimit(). Proceeding.");
  296. return 0; /* hope we'll be ok */
  297. #else
  298. struct rlimit rlim;
  299. if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
  300. log_fn(LOG_WARN, "Could not get maximum number of file descriptors: %s",
  301. strerror(errno));
  302. return -1;
  303. }
  304. if(required_min > rlim.rlim_max) {
  305. log_fn(LOG_WARN,"We need %d file descriptors available, and we're limited to %d. Please change your ulimit.", required_min, (int)rlim.rlim_max);
  306. return -1;
  307. }
  308. if(required_min > rlim.rlim_cur) {
  309. log_fn(LOG_INFO,"Raising max file descriptors from %d to %d.",
  310. (int)rlim.rlim_cur, (int)rlim.rlim_max);
  311. }
  312. rlim.rlim_cur = rlim.rlim_max;
  313. if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
  314. log_fn(LOG_WARN, "Could not set maximum number of file descriptors: %s",
  315. strerror(errno));
  316. return -1;
  317. }
  318. return 0;
  319. #endif
  320. }
  321. /** Call setuid and setgid to run as <b>user</b>:<b>group</b>. Return 0 on
  322. * success. On failure, log and return -1.
  323. */
  324. int switch_id(char *user, char *group) {
  325. #ifndef MS_WINDOWS
  326. struct passwd *pw = NULL;
  327. struct group *gr = NULL;
  328. if (user) {
  329. pw = getpwnam(user);
  330. if (pw == NULL) {
  331. log_fn(LOG_ERR,"User '%s' not found.", user);
  332. return -1;
  333. }
  334. }
  335. /* switch the group first, while we still have the privileges to do so */
  336. if (group) {
  337. gr = getgrnam(group);
  338. if (gr == NULL) {
  339. log_fn(LOG_ERR,"Group '%s' not found.", group);
  340. return -1;
  341. }
  342. if (setgid(gr->gr_gid) != 0) {
  343. log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
  344. return -1;
  345. }
  346. } else if (user) {
  347. if (setgid(pw->pw_gid) != 0) {
  348. log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
  349. return -1;
  350. }
  351. }
  352. /* now that the group is switched, we can switch users and lose
  353. privileges */
  354. if (user) {
  355. if (setuid(pw->pw_uid) != 0) {
  356. log_fn(LOG_ERR,"Error setting UID: %s", strerror(errno));
  357. return -1;
  358. }
  359. }
  360. return 0;
  361. #endif
  362. log_fn(LOG_ERR,
  363. "User or group specified, but switching users is not supported.");
  364. return -1;
  365. }
  366. /** Set *addr to the IP address (in dotted-quad notation) stored in c.
  367. * Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr),
  368. * but works on Windows and Solaris.)
  369. */
  370. int tor_inet_aton(const char *c, struct in_addr* addr)
  371. {
  372. #ifdef HAVE_INET_ATON
  373. return inet_aton(c, addr);
  374. #else
  375. uint32_t r;
  376. tor_assert(c);
  377. tor_assert(addr);
  378. if (strcmp(c, "255.255.255.255") == 0) {
  379. addr->s_addr = 0xFFFFFFFFu;
  380. return 1;
  381. }
  382. r = inet_addr(c);
  383. if (r == INADDR_NONE)
  384. return 0;
  385. addr->s_addr = r;
  386. return 1;
  387. #endif
  388. }
  389. /* Hold the result of our call to <b>uname</b>. */
  390. static char uname_result[256];
  391. /* True iff uname_result is set. */
  392. static int uname_result_is_set = 0;
  393. /* Return a pointer to a description of our platform.
  394. */
  395. const char *
  396. get_uname(void)
  397. {
  398. #ifdef HAVE_UNAME
  399. struct utsname u;
  400. #endif
  401. if (!uname_result_is_set) {
  402. #ifdef HAVE_UNAME
  403. if (uname(&u) != -1) {
  404. /* (linux says 0 is success, solaris says 1 is success) */
  405. tor_snprintf(uname_result, sizeof(uname_result), "%s %s %s",
  406. u.sysname, u.nodename, u.machine);
  407. } else
  408. #endif
  409. {
  410. strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
  411. }
  412. uname_result_is_set = 1;
  413. }
  414. return uname_result;
  415. }
  416. /*
  417. * Process control
  418. */
  419. /** Minimalist interface to run a void function in the background. On
  420. * unix calls fork, on win32 calls beginthread. Returns -1 on failure.
  421. * func should not return, but rather should call spawn_exit.
  422. */
  423. int spawn_func(int (*func)(void *), void *data)
  424. {
  425. #ifdef MS_WINDOWS
  426. int rv;
  427. rv = _beginthread(func, 0, data);
  428. if (rv == (unsigned long) -1)
  429. return -1;
  430. return 0;
  431. #else
  432. pid_t pid;
  433. pid = fork();
  434. if (pid<0)
  435. return -1;
  436. if (pid==0) {
  437. /* Child */
  438. func(data);
  439. tor_assert(0); /* Should never reach here. */
  440. return 0; /* suppress "control-reaches-end-of-non-void" warning. */
  441. } else {
  442. /* Parent */
  443. return 0;
  444. }
  445. #endif
  446. }
  447. /** End the current thread/process.
  448. */
  449. void spawn_exit()
  450. {
  451. #ifdef MS_WINDOWS
  452. _endthread();
  453. #else
  454. exit(0);
  455. #endif
  456. }
  457. /** Set *timeval to the current time of day. On error, log and terminate.
  458. * (Same as gettimeofday(timeval,NULL), but never returns -1.)
  459. */
  460. void tor_gettimeofday(struct timeval *timeval) {
  461. #ifdef HAVE_GETTIMEOFDAY
  462. if (gettimeofday(timeval, NULL)) {
  463. log_fn(LOG_ERR, "gettimeofday failed.");
  464. /* If gettimeofday dies, we have either given a bad timezone (we didn't),
  465. or segfaulted.*/
  466. exit(1);
  467. }
  468. #elif defined(HAVE_FTIME)
  469. struct timeb tb;
  470. ftime(&tb);
  471. timeval->tv_sec = tb.time;
  472. timeval->tv_usec = tb.millitm * 1000;
  473. #else
  474. #error "No way to get time."
  475. #endif
  476. return;
  477. }
  478. #ifndef MS_WINDOWS
  479. struct tor_mutex_t {
  480. };
  481. tor_mutex_t *tor_mutex_new(void) { return NULL; }
  482. void tor_mutex_acquire(tor_mutex_t *m) { }
  483. void tor_mutex_release(tor_mutex_t *m) { }
  484. void tor_mutex_free(tor_mutex_t *m) { }
  485. #else
  486. struct tor_mutex_t {
  487. HANDLE handle;
  488. };
  489. tor_mutex_t *tor_mutex_new(void)
  490. {
  491. tor_mutex_t *m;
  492. m = tor_malloc_zero(sizeof(tor_mutex_t));
  493. m->handle = CreateMutex(NULL, FALSE, NULL);
  494. tor_assert(m->handle != NULL);
  495. return m;
  496. }
  497. void tor_mutex_free(tor_mutex_t *m)
  498. {
  499. CloseHandle(m->handle);
  500. tor_free(m);
  501. }
  502. void tor_mutex_acquire(tor_mutex_t *m)
  503. {
  504. DWORD r;
  505. r = WaitForSingleObject(m->handle, INFINITE);
  506. switch (r) {
  507. case WAIT_ABANDONED: /* holding thread exited. */
  508. case WAIT_OBJECT_0: /* we got the mutex normally. */
  509. break;
  510. case WAIT_TIMEOUT: /* Should never happen. */
  511. tor_assert(0);
  512. break;
  513. case WAIT_FAILED:
  514. log_fn(LOG_WARN, "Failed to acquire mutex: %d", GetLastError());
  515. }
  516. }
  517. void tor_mutex_release(tor_mutex_t *m)
  518. {
  519. BOOL r;
  520. r = ReleaseMutex(m->handle);
  521. if (!r) {
  522. log_fn(LOG_WARN, "Failed to release mutex: %d", GetLastError());
  523. }
  524. }
  525. #endif
  526. /**
  527. * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
  528. * you need to ask the socket for its actual errno. Also, you need to
  529. * get your errors from WSAGetLastError, not errno. (If you supply a
  530. * socket of -1, we check WSAGetLastError, but don't correct
  531. * WSAEWOULDBLOCKs.)
  532. */
  533. #ifdef MS_WINDOWS
  534. int tor_socket_errno(int sock)
  535. {
  536. int optval, optvallen=sizeof(optval);
  537. int err = WSAGetLastError();
  538. if (err == WSAEWOULDBLOCK && sock >= 0) {
  539. if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
  540. return err;
  541. if (optval)
  542. return optval;
  543. }
  544. return err;
  545. }
  546. #endif
  547. #ifdef MS_WINDOWS
  548. #define E(code, s) { code, (s " [" #code " ]") }
  549. struct { int code; const char *msg; } windows_socket_errors[] = {
  550. E(WSAEINTR, "Interrupted function call"),
  551. E(WSAEACCES, "Permission denied"),
  552. E(WSAEFAULT, "Bad address"),
  553. E(WSAEINVAL, "Invalid argument"),
  554. E(WSAEMFILE, "Too many open files"),
  555. E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
  556. E(WSAEINPROGRESS, "Operation now in progress"),
  557. E(WSAEALREADY, "Operation already in progress"),
  558. E(WSAENOTSOCK, "Socket operation on nonsocket"),
  559. E(WSAEDESTADDRREQ, "Destination address required"),
  560. E(WSAEMSGSIZE, "Message too long"),
  561. E(WSAEPROTOTYPE, "Protocol wrong for socket"),
  562. E(WSAENOPROTOOPT, "Bad protocol option"),
  563. E(WSAEPROTONOSUPPORT, "Protocol not supported"),
  564. E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
  565. /* What's the difference between NOTSUPP and NOSUPPORT? :) */
  566. E(WSAEOPNOTSUPP, "Operation not supported"),
  567. E(WSAEPFNOSUPPORT, "Protocol family not supported"),
  568. E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
  569. E(WSAEADDRINUSE, "Address already in use"),
  570. E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
  571. E(WSAENETDOWN, "Network is down"),
  572. E(WSAENETUNREACH, "Network is unreachable"),
  573. E(WSAENETRESET, "Network dropped connection on reset"),
  574. E(WSAECONNABORTED, "Software caused connection abort"),
  575. E(WSAECONNRESET, "Connection reset by peer"),
  576. E(WSAENOBUFS, "No buffer space avaialable"),
  577. E(WSAEISCONN, "Socket is already connected"),
  578. E(WSAENOTCONN, "Socket is not connected"),
  579. E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
  580. E(WSAETIMEDOUT, "Connection timed out"),
  581. E(WSAECONNREFUSED, "Connection refused"),
  582. E(WSAEHOSTDOWN, "Host is down"),
  583. E(WSAEHOSTUNREACH, "No route to host"),
  584. E(WSAEPROCLIM, "Too many processes"),
  585. /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
  586. E(WSASYSNOTREADY, "Network subsystem is unavailable"),
  587. E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
  588. E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
  589. E(WSAEDISCON, "Graceful shutdown now in progress"),
  590. #ifdef WSATYPE_NOT_FOUND
  591. E(WSATYPE_NOT_FOUND, "Class type not found"),
  592. #endif
  593. E(WSAHOST_NOT_FOUND, "Host not found"),
  594. E(WSATRY_AGAIN, "Nonauthoritative host not found"),
  595. E(WSANO_RECOVERY, "This is a nonrecoverable error"),
  596. E(WSANO_DATA, "Valid name, no data record of requested type)"),
  597. /* There are some more error codes whose numeric values are marked
  598. * <b>OS dependent</b>. They start with WSA_, apparently for the same
  599. * reason that practitioners of some craft traditions deliberately
  600. * introduce imperfections into their baskets and rugs "to allow the
  601. * evil spirits to escape." If we catch them, then our binaries
  602. * might not report consistent results across versions of Windows.
  603. * Thus, I'm going to let them all fall through.
  604. */
  605. { -1, NULL },
  606. };
  607. /** There does not seem to be a strerror equivalent for winsock errors.
  608. * Naturally, we have to roll our own.
  609. */
  610. const char *tor_socket_strerror(int e)
  611. {
  612. int i;
  613. for (i=0; windows_socket_errors[i].code >= 0; ++i) {
  614. if (e == windows_socket_errors[i].code)
  615. return windows_socket_errors[i].msg;
  616. }
  617. return strerror(e);
  618. }
  619. #endif
  620. /*
  621. Local Variables:
  622. mode:c
  623. indent-tabs-mode:nil
  624. c-basic-offset:2
  625. End:
  626. */