PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/openvpn/error.c

https://github.com/alex-vpn/openvpn
C | 912 lines | 696 code | 111 blank | 105 comment | 102 complexity | e81f23a3c68090ffc3fb6b5520fcc6e2 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0
  1. /*
  2. * OpenVPN -- An application to securely tunnel IP networks
  3. * over a single TCP/UDP port, with support for SSL/TLS-based
  4. * session authentication and key exchange,
  5. * packet encryption, packet authentication, and
  6. * packet compression.
  7. *
  8. * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #elif defined(_MSC_VER)
  27. #include "config-msvc.h"
  28. #endif
  29. #include "syshead.h"
  30. #include "error.h"
  31. #include "buffer.h"
  32. #include "misc.h"
  33. #include "win32.h"
  34. #include "socket.h"
  35. #include "tun.h"
  36. #include "otime.h"
  37. #include "perf.h"
  38. #include "status.h"
  39. #include "integer.h"
  40. #include "ps.h"
  41. #include "mstats.h"
  42. #ifdef ENABLE_CRYPTO
  43. #ifdef ENABLE_CRYPTO_OPENSSL
  44. #include <openssl/err.h>
  45. #endif
  46. #endif
  47. #include "memdbg.h"
  48. #if SYSLOG_CAPABILITY
  49. #ifndef LOG_OPENVPN
  50. #define LOG_OPENVPN LOG_DAEMON
  51. #endif
  52. #endif
  53. /* Globals */
  54. unsigned int x_debug_level; /* GLOBAL */
  55. /* Mute state */
  56. static int mute_cutoff; /* GLOBAL */
  57. static int mute_count; /* GLOBAL */
  58. static int mute_category; /* GLOBAL */
  59. /*
  60. * Output mode priorities are as follows:
  61. *
  62. * (1) --log-x overrides everything
  63. * (2) syslog is used if --daemon or --inetd is defined and not --log-x
  64. * (3) if OPENVPN_DEBUG_COMMAND_LINE is defined, output
  65. * to constant logfile name.
  66. * (4) Output to stdout.
  67. */
  68. /* If true, indicates that stdin/stdout/stderr
  69. have been redirected due to --log */
  70. static bool std_redir; /* GLOBAL */
  71. /* Should messages be written to the syslog? */
  72. static bool use_syslog; /* GLOBAL */
  73. /* Should stdout/stderr be be parsable and always be prefixed with time
  74. * and message flags */
  75. static bool machine_readable_output; /* GLOBAL */
  76. /* Should timestamps be included on messages to stdout/stderr? */
  77. static bool suppress_timestamps; /* GLOBAL */
  78. /* The program name passed to syslog */
  79. #if SYSLOG_CAPABILITY
  80. static char *pgmname_syslog; /* GLOBAL */
  81. #endif
  82. /* If non-null, messages should be written here (used for debugging only) */
  83. static FILE *msgfp; /* GLOBAL */
  84. /* If true, we forked from main OpenVPN process */
  85. static bool forked; /* GLOBAL */
  86. /* our default output targets */
  87. static FILE *default_out; /* GLOBAL */
  88. static FILE *default_err; /* GLOBAL */
  89. void
  90. msg_forked (void)
  91. {
  92. forked = true;
  93. }
  94. bool
  95. set_debug_level (const int level, const unsigned int flags)
  96. {
  97. const int ceiling = 15;
  98. if (level >= 0 && level <= ceiling)
  99. {
  100. x_debug_level = level;
  101. return true;
  102. }
  103. else if (flags & SDL_CONSTRAIN)
  104. {
  105. x_debug_level = constrain_int (level, 0, ceiling);
  106. return true;
  107. }
  108. return false;
  109. }
  110. bool
  111. set_mute_cutoff (const int cutoff)
  112. {
  113. if (cutoff >= 0)
  114. {
  115. mute_cutoff = cutoff;
  116. return true;
  117. }
  118. else
  119. return false;
  120. }
  121. int
  122. get_debug_level (void)
  123. {
  124. return x_debug_level;
  125. }
  126. int
  127. get_mute_cutoff (void)
  128. {
  129. return mute_cutoff;
  130. }
  131. void
  132. set_suppress_timestamps (bool suppressed)
  133. {
  134. suppress_timestamps = suppressed;
  135. }
  136. void
  137. set_machine_readable_output (bool parsable)
  138. {
  139. machine_readable_output = parsable;
  140. }
  141. void
  142. error_reset ()
  143. {
  144. use_syslog = std_redir = false;
  145. suppress_timestamps = false;
  146. machine_readable_output = false;
  147. x_debug_level = 1;
  148. mute_cutoff = 0;
  149. mute_count = 0;
  150. mute_category = 0;
  151. default_out = OPENVPN_MSG_FP;
  152. default_err = OPENVPN_MSG_FP;
  153. #ifdef OPENVPN_DEBUG_COMMAND_LINE
  154. msgfp = fopen (OPENVPN_DEBUG_FILE, "w");
  155. if (!msgfp)
  156. openvpn_exit (OPENVPN_EXIT_STATUS_CANNOT_OPEN_DEBUG_FILE); /* exit point */
  157. #else
  158. msgfp = NULL;
  159. #endif
  160. }
  161. void
  162. errors_to_stderr (void)
  163. {
  164. default_err = OPENVPN_ERROR_FP;
  165. }
  166. /*
  167. * Return a file to print messages to before syslog is opened.
  168. */
  169. FILE *
  170. msg_fp(const unsigned int flags)
  171. {
  172. FILE *fp = msgfp;
  173. if (!fp)
  174. fp = (flags & (M_FATAL|M_USAGE_SMALL)) ? default_err : default_out;
  175. if (!fp)
  176. openvpn_exit (OPENVPN_EXIT_STATUS_CANNOT_OPEN_DEBUG_FILE); /* exit point */
  177. return fp;
  178. }
  179. #define SWAP { tmp = m1; m1 = m2; m2 = tmp; }
  180. int x_msg_line_num; /* GLOBAL */
  181. void x_msg (const unsigned int flags, const char *format, ...)
  182. {
  183. va_list arglist;
  184. va_start (arglist, format);
  185. x_msg_va (flags, format, arglist);
  186. va_end (arglist);
  187. }
  188. void x_msg_va (const unsigned int flags, const char *format, va_list arglist)
  189. {
  190. struct gc_arena gc;
  191. #if SYSLOG_CAPABILITY
  192. int level;
  193. #endif
  194. char *m1;
  195. char *m2;
  196. char *tmp;
  197. int e;
  198. const char *prefix;
  199. const char *prefix_sep;
  200. void usage_small (void);
  201. #ifndef HAVE_VARARG_MACROS
  202. /* the macro has checked this otherwise */
  203. if (!MSG_TEST (flags))
  204. return;
  205. #endif
  206. e = openvpn_errno ();
  207. /*
  208. * Apply muting filter.
  209. */
  210. #ifndef HAVE_VARARG_MACROS
  211. /* the macro has checked this otherwise */
  212. if (!dont_mute (flags))
  213. return;
  214. #endif
  215. gc_init (&gc);
  216. m1 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc);
  217. m2 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc);
  218. vsnprintf (m1, ERR_BUF_SIZE, format, arglist);
  219. m1[ERR_BUF_SIZE - 1] = 0; /* windows vsnprintf needs this */
  220. if ((flags & M_ERRNO) && e)
  221. {
  222. openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s (errno=%d)",
  223. m1, strerror_ts (e, &gc), e);
  224. SWAP;
  225. }
  226. #ifdef ENABLE_CRYPTO
  227. #ifdef ENABLE_CRYPTO_OPENSSL
  228. if (flags & M_SSL)
  229. {
  230. int nerrs = 0;
  231. size_t err;
  232. while ((err = ERR_get_error ()))
  233. {
  234. openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s",
  235. m1, ERR_error_string (err, NULL));
  236. SWAP;
  237. ++nerrs;
  238. }
  239. if (!nerrs)
  240. {
  241. openvpn_snprintf (m2, ERR_BUF_SIZE, "%s (OpenSSL)", m1);
  242. SWAP;
  243. }
  244. }
  245. #endif
  246. #endif
  247. if (flags & M_OPTERR)
  248. {
  249. openvpn_snprintf (m2, ERR_BUF_SIZE, "Options error: %s", m1);
  250. SWAP;
  251. }
  252. #if SYSLOG_CAPABILITY
  253. if (flags & (M_FATAL|M_NONFATAL|M_USAGE_SMALL))
  254. level = LOG_ERR;
  255. else if (flags & M_WARN)
  256. level = LOG_WARNING;
  257. else
  258. level = LOG_NOTICE;
  259. #endif
  260. /* set up client prefix */
  261. if (flags & M_NOIPREFIX)
  262. prefix = NULL;
  263. else
  264. prefix = msg_get_prefix ();
  265. prefix_sep = " ";
  266. if (!prefix)
  267. prefix_sep = prefix = "";
  268. /* virtual output capability used to copy output to management subsystem */
  269. if (!forked)
  270. {
  271. const struct virtual_output *vo = msg_get_virtual_output ();
  272. if (vo)
  273. {
  274. openvpn_snprintf (m2, ERR_BUF_SIZE, "%s%s%s",
  275. prefix,
  276. prefix_sep,
  277. m1);
  278. virtual_output_print (vo, flags, m2);
  279. }
  280. }
  281. if (!(flags & M_MSG_VIRT_OUT))
  282. {
  283. if (use_syslog && !std_redir && !forked)
  284. {
  285. #if SYSLOG_CAPABILITY
  286. syslog (level, "%s%s%s",
  287. prefix,
  288. prefix_sep,
  289. m1);
  290. #endif
  291. }
  292. else
  293. {
  294. FILE *fp = msg_fp(flags);
  295. const bool show_usec = check_debug_level (DEBUG_LEVEL_USEC_TIME);
  296. if (machine_readable_output)
  297. {
  298. struct timeval tv;
  299. gettimeofday (&tv, NULL);
  300. fprintf (fp, "%lu.%06lu %x %s%s%s%s",
  301. tv.tv_sec,
  302. tv.tv_usec,
  303. flags,
  304. prefix,
  305. prefix_sep,
  306. m1,
  307. "\n");
  308. }
  309. else if ((flags & M_NOPREFIX) || suppress_timestamps)
  310. {
  311. fprintf (fp, "%s%s%s%s",
  312. prefix,
  313. prefix_sep,
  314. m1,
  315. (flags&M_NOLF) ? "" : "\n");
  316. }
  317. else
  318. {
  319. fprintf (fp, "%s %s%s%s%s",
  320. time_string (0, 0, show_usec, &gc),
  321. prefix,
  322. prefix_sep,
  323. m1,
  324. (flags&M_NOLF) ? "" : "\n");
  325. }
  326. fflush(fp);
  327. ++x_msg_line_num;
  328. }
  329. }
  330. if (flags & M_FATAL)
  331. msg (M_INFO, "Exiting due to fatal error");
  332. if (flags & M_FATAL)
  333. openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */
  334. if (flags & M_USAGE_SMALL)
  335. usage_small ();
  336. gc_free (&gc);
  337. }
  338. /*
  339. * Apply muting filter.
  340. */
  341. bool
  342. dont_mute (unsigned int flags)
  343. {
  344. bool ret = true;
  345. if (mute_cutoff > 0 && !(flags & M_NOMUTE))
  346. {
  347. const int mute_level = DECODE_MUTE_LEVEL (flags);
  348. if (mute_level > 0 && mute_level == mute_category)
  349. {
  350. if (mute_count == mute_cutoff)
  351. msg (M_INFO | M_NOMUTE, "NOTE: --mute triggered...");
  352. if (++mute_count > mute_cutoff)
  353. ret = false;
  354. }
  355. else
  356. {
  357. const int suppressed = mute_count - mute_cutoff;
  358. if (suppressed > 0)
  359. msg (M_INFO | M_NOMUTE,
  360. "%d variation(s) on previous %d message(s) suppressed by --mute",
  361. suppressed,
  362. mute_cutoff);
  363. mute_count = 1;
  364. mute_category = mute_level;
  365. }
  366. }
  367. return ret;
  368. }
  369. void
  370. assert_failed (const char *filename, int line)
  371. {
  372. msg (M_FATAL, "Assertion failed at %s:%d", filename, line);
  373. }
  374. /*
  375. * Fail memory allocation. Don't use msg() because it tries
  376. * to allocate memory as part of its operation.
  377. */
  378. void
  379. out_of_memory (void)
  380. {
  381. fprintf (stderr, PACKAGE_NAME ": Out of Memory\n");
  382. exit (1);
  383. }
  384. void
  385. open_syslog (const char *pgmname, bool stdio_to_null)
  386. {
  387. #if SYSLOG_CAPABILITY
  388. if (!msgfp && !std_redir)
  389. {
  390. if (!use_syslog)
  391. {
  392. pgmname_syslog = string_alloc (pgmname ? pgmname : PACKAGE, NULL);
  393. openlog (pgmname_syslog, LOG_PID, LOG_OPENVPN);
  394. use_syslog = true;
  395. /* Better idea: somehow pipe stdout/stderr output to msg() */
  396. if (stdio_to_null)
  397. set_std_files_to_null (false);
  398. }
  399. }
  400. #else
  401. msg (M_WARN, "Warning on use of --daemon/--inetd: this operating system lacks daemon logging features, therefore when I become a daemon, I won't be able to log status or error messages");
  402. #endif
  403. }
  404. void
  405. close_syslog ()
  406. {
  407. #if SYSLOG_CAPABILITY
  408. if (use_syslog)
  409. {
  410. closelog();
  411. use_syslog = false;
  412. if (pgmname_syslog)
  413. {
  414. free (pgmname_syslog);
  415. pgmname_syslog = NULL;
  416. }
  417. }
  418. #endif
  419. }
  420. #ifdef WIN32
  421. static HANDLE orig_stderr;
  422. HANDLE
  423. get_orig_stderr (void)
  424. {
  425. if (orig_stderr)
  426. return orig_stderr;
  427. else
  428. return GetStdHandle (STD_ERROR_HANDLE);
  429. }
  430. #endif
  431. void
  432. redirect_stdout_stderr (const char *file, bool append)
  433. {
  434. #if defined(WIN32)
  435. if (!std_redir)
  436. {
  437. struct gc_arena gc = gc_new ();
  438. HANDLE log_handle;
  439. int log_fd;
  440. SECURITY_ATTRIBUTES saAttr;
  441. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  442. saAttr.bInheritHandle = TRUE;
  443. saAttr.lpSecurityDescriptor = NULL;
  444. log_handle = CreateFileW (wide_string (file, &gc),
  445. GENERIC_WRITE,
  446. FILE_SHARE_READ,
  447. &saAttr,
  448. append ? OPEN_ALWAYS : CREATE_ALWAYS,
  449. FILE_ATTRIBUTE_NORMAL,
  450. NULL);
  451. gc_free (&gc);
  452. if (log_handle == INVALID_HANDLE_VALUE)
  453. {
  454. msg (M_WARN|M_ERRNO, "Warning: cannot open --log file: %s", file);
  455. return;
  456. }
  457. /* append to logfile? */
  458. if (append)
  459. {
  460. if (SetFilePointer (log_handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
  461. msg (M_ERR, "Error: cannot seek to end of --log file: %s", file);
  462. }
  463. /* save original stderr for password prompts */
  464. orig_stderr = GetStdHandle (STD_ERROR_HANDLE);
  465. #if 0 /* seems not be necessary with stdout/stderr redirection below*/
  466. /* set up for redirection */
  467. if (!SetStdHandle (STD_OUTPUT_HANDLE, log_handle)
  468. || !SetStdHandle (STD_ERROR_HANDLE, log_handle))
  469. msg (M_ERR, "Error: cannot redirect stdout/stderr to --log file: %s", file);
  470. #endif
  471. /* direct stdout/stderr to point to log_handle */
  472. log_fd = _open_osfhandle ((intptr_t)log_handle, _O_TEXT);
  473. if (log_fd == -1)
  474. msg (M_ERR, "Error: --log redirect failed due to _open_osfhandle failure");
  475. /* open log_handle as FILE stream */
  476. ASSERT (msgfp == NULL);
  477. msgfp = _fdopen (log_fd, "wt");
  478. if (msgfp == NULL)
  479. msg (M_ERR, "Error: --log redirect failed due to _fdopen");
  480. /* redirect C-library stdout/stderr to log file */
  481. if (_dup2 (log_fd, 1) == -1 || _dup2 (log_fd, 2) == -1)
  482. msg (M_WARN, "Error: --log redirect of stdout/stderr failed");
  483. std_redir = true;
  484. }
  485. #elif defined(HAVE_DUP2)
  486. if (!std_redir)
  487. {
  488. int out = open (file,
  489. O_CREAT | O_WRONLY | (append ? O_APPEND : O_TRUNC),
  490. S_IRUSR | S_IWUSR);
  491. if (out < 0)
  492. {
  493. msg (M_WARN|M_ERRNO, "Warning: Error redirecting stdout/stderr to --log file: %s", file);
  494. return;
  495. }
  496. if (dup2 (out, 1) == -1)
  497. msg (M_ERR, "--log file redirection error on stdout");
  498. if (dup2 (out, 2) == -1)
  499. msg (M_ERR, "--log file redirection error on stderr");
  500. if (out > 2)
  501. close (out);
  502. std_redir = true;
  503. }
  504. #else
  505. msg (M_WARN, "WARNING: The --log option is not supported on this OS because it lacks the dup2 function");
  506. #endif
  507. }
  508. /*
  509. * Functions used to check return status
  510. * of I/O operations.
  511. */
  512. unsigned int x_cs_info_level; /* GLOBAL */
  513. unsigned int x_cs_verbose_level; /* GLOBAL */
  514. unsigned int x_cs_err_delay_ms; /* GLOBAL */
  515. void
  516. reset_check_status ()
  517. {
  518. x_cs_info_level = 0;
  519. x_cs_verbose_level = 0;
  520. }
  521. void
  522. set_check_status (unsigned int info_level, unsigned int verbose_level)
  523. {
  524. x_cs_info_level = info_level;
  525. x_cs_verbose_level = verbose_level;
  526. }
  527. /*
  528. * Called after most socket or tun/tap operations, via the inline
  529. * function check_status().
  530. *
  531. * Decide if we should print an error message, and see if we can
  532. * extract any useful info from the error, such as a Path MTU hint
  533. * from the OS.
  534. */
  535. void
  536. x_check_status (int status,
  537. const char *description,
  538. struct link_socket *sock,
  539. struct tuntap *tt)
  540. {
  541. const int my_errno = openvpn_errno ();
  542. const char *extended_msg = NULL;
  543. msg (x_cs_verbose_level, "%s %s returned %d",
  544. sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
  545. description,
  546. status);
  547. if (status < 0)
  548. {
  549. struct gc_arena gc = gc_new ();
  550. #if EXTENDED_SOCKET_ERROR_CAPABILITY
  551. /* get extended socket error message and possible PMTU hint from OS */
  552. if (sock)
  553. {
  554. int mtu;
  555. extended_msg = format_extended_socket_error (sock->sd, &mtu, &gc);
  556. if (mtu > 0 && sock->mtu != mtu)
  557. {
  558. sock->mtu = mtu;
  559. sock->info.mtu_changed = true;
  560. }
  561. }
  562. #elif defined(WIN32)
  563. /* get possible driver error from TAP-Windows driver */
  564. extended_msg = tap_win_getinfo (tt, &gc);
  565. #endif
  566. if (!ignore_sys_error (my_errno))
  567. {
  568. if (extended_msg)
  569. msg (x_cs_info_level, "%s %s [%s]: %s (code=%d)",
  570. description,
  571. sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
  572. extended_msg,
  573. strerror_ts (my_errno, &gc),
  574. my_errno);
  575. else
  576. msg (x_cs_info_level, "%s %s: %s (code=%d)",
  577. description,
  578. sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
  579. strerror_ts (my_errno, &gc),
  580. my_errno);
  581. if (x_cs_err_delay_ms)
  582. platform_sleep_milliseconds (x_cs_err_delay_ms);
  583. }
  584. gc_free (&gc);
  585. }
  586. }
  587. /*
  588. * In multiclient mode, put a client-specific prefix
  589. * before each message.
  590. */
  591. const char *x_msg_prefix; /* GLOBAL */
  592. /*
  593. * Allow MSG to be redirected through a virtual_output object
  594. */
  595. const struct virtual_output *x_msg_virtual_output; /* GLOBAL */
  596. /*
  597. * Exiting.
  598. */
  599. void
  600. openvpn_exit (const int status)
  601. {
  602. if (!forked)
  603. {
  604. void tun_abort();
  605. #ifdef ENABLE_PLUGIN
  606. void plugin_abort (void);
  607. #endif
  608. tun_abort();
  609. #ifdef WIN32
  610. uninit_win32 ();
  611. #endif
  612. close_syslog ();
  613. #ifdef ENABLE_PLUGIN
  614. plugin_abort ();
  615. #endif
  616. #if PORT_SHARE
  617. if (port_share)
  618. port_share_abort (port_share);
  619. #endif
  620. #ifdef ENABLE_MEMSTATS
  621. mstats_close();
  622. #endif
  623. #ifdef ABORT_ON_ERROR
  624. if (status == OPENVPN_EXIT_STATUS_ERROR)
  625. abort ();
  626. #endif
  627. if (status == OPENVPN_EXIT_STATUS_GOOD)
  628. perf_output_results ();
  629. }
  630. exit (status);
  631. }
  632. /*
  633. * Translate msg flags into a string
  634. */
  635. const char *
  636. msg_flags_string (const unsigned int flags, struct gc_arena *gc)
  637. {
  638. struct buffer out = alloc_buf_gc (16, gc);
  639. if (flags == M_INFO)
  640. buf_printf (&out, "I");
  641. if (flags & M_FATAL)
  642. buf_printf (&out, "F");
  643. if (flags & M_NONFATAL)
  644. buf_printf (&out, "N");
  645. if (flags & M_WARN)
  646. buf_printf (&out, "W");
  647. if (flags & M_DEBUG)
  648. buf_printf (&out, "D");
  649. return BSTR (&out);
  650. }
  651. #ifdef ENABLE_DEBUG
  652. void
  653. crash (void)
  654. {
  655. char *null = NULL;
  656. *null = 0;
  657. }
  658. #endif
  659. #ifdef WIN32
  660. const char *
  661. strerror_win32 (DWORD errnum, struct gc_arena *gc)
  662. {
  663. /*
  664. * This code can be omitted, though often the Windows
  665. * WSA error messages are less informative than the
  666. * Posix equivalents.
  667. */
  668. #if 1
  669. switch (errnum) {
  670. /*
  671. * When the TAP-Windows driver returns STATUS_UNSUCCESSFUL, this code
  672. * gets returned to user space.
  673. */
  674. case ERROR_GEN_FAILURE:
  675. return "General failure (ERROR_GEN_FAILURE)";
  676. case ERROR_IO_PENDING:
  677. return "I/O Operation in progress (ERROR_IO_PENDING)";
  678. case WSA_IO_INCOMPLETE:
  679. return "I/O Operation in progress (WSA_IO_INCOMPLETE)";
  680. case WSAEINTR:
  681. return "Interrupted system call (WSAEINTR)";
  682. case WSAEBADF:
  683. return "Bad file number (WSAEBADF)";
  684. case WSAEACCES:
  685. return "Permission denied (WSAEACCES)";
  686. case WSAEFAULT:
  687. return "Bad address (WSAEFAULT)";
  688. case WSAEINVAL:
  689. return "Invalid argument (WSAEINVAL)";
  690. case WSAEMFILE:
  691. return "Too many open files (WSAEMFILE)";
  692. case WSAEWOULDBLOCK:
  693. return "Operation would block (WSAEWOULDBLOCK)";
  694. case WSAEINPROGRESS:
  695. return "Operation now in progress (WSAEINPROGRESS)";
  696. case WSAEALREADY:
  697. return "Operation already in progress (WSAEALREADY)";
  698. case WSAEDESTADDRREQ:
  699. return "Destination address required (WSAEDESTADDRREQ)";
  700. case WSAEMSGSIZE:
  701. return "Message too long (WSAEMSGSIZE)";
  702. case WSAEPROTOTYPE:
  703. return "Protocol wrong type for socket (WSAEPROTOTYPE)";
  704. case WSAENOPROTOOPT:
  705. return "Bad protocol option (WSAENOPROTOOPT)";
  706. case WSAEPROTONOSUPPORT:
  707. return "Protocol not supported (WSAEPROTONOSUPPORT)";
  708. case WSAESOCKTNOSUPPORT:
  709. return "Socket type not supported (WSAESOCKTNOSUPPORT)";
  710. case WSAEOPNOTSUPP:
  711. return "Operation not supported on socket (WSAEOPNOTSUPP)";
  712. case WSAEPFNOSUPPORT:
  713. return "Protocol family not supported (WSAEPFNOSUPPORT)";
  714. case WSAEAFNOSUPPORT:
  715. return "Address family not supported by protocol family (WSAEAFNOSUPPORT)";
  716. case WSAEADDRINUSE:
  717. return "Address already in use (WSAEADDRINUSE)";
  718. case WSAENETDOWN:
  719. return "Network is down (WSAENETDOWN)";
  720. case WSAENETUNREACH:
  721. return "Network is unreachable (WSAENETUNREACH)";
  722. case WSAENETRESET:
  723. return "Net dropped connection or reset (WSAENETRESET)";
  724. case WSAECONNABORTED:
  725. return "Software caused connection abort (WSAECONNABORTED)";
  726. case WSAECONNRESET:
  727. return "Connection reset by peer (WSAECONNRESET)";
  728. case WSAENOBUFS:
  729. return "No buffer space available (WSAENOBUFS)";
  730. case WSAEISCONN:
  731. return "Socket is already connected (WSAEISCONN)";
  732. case WSAENOTCONN:
  733. return "Socket is not connected (WSAENOTCONN)";
  734. case WSAETIMEDOUT:
  735. return "Connection timed out (WSAETIMEDOUT)";
  736. case WSAECONNREFUSED:
  737. return "Connection refused (WSAECONNREFUSED)";
  738. case WSAELOOP:
  739. return "Too many levels of symbolic links (WSAELOOP)";
  740. case WSAENAMETOOLONG:
  741. return "File name too long (WSAENAMETOOLONG)";
  742. case WSAEHOSTDOWN:
  743. return "Host is down (WSAEHOSTDOWN)";
  744. case WSAEHOSTUNREACH:
  745. return "No Route to Host (WSAEHOSTUNREACH)";
  746. case WSAENOTEMPTY:
  747. return "Directory not empty (WSAENOTEMPTY)";
  748. case WSAEPROCLIM:
  749. return "Too many processes (WSAEPROCLIM)";
  750. case WSAEUSERS:
  751. return "Too many users (WSAEUSERS)";
  752. case WSAEDQUOT:
  753. return "Disc Quota Exceeded (WSAEDQUOT)";
  754. case WSAESTALE:
  755. return "Stale NFS file handle (WSAESTALE)";
  756. case WSASYSNOTREADY:
  757. return "Network SubSystem is unavailable (WSASYSNOTREADY)";
  758. case WSAVERNOTSUPPORTED:
  759. return "WINSOCK DLL Version out of range (WSAVERNOTSUPPORTED)";
  760. case WSANOTINITIALISED:
  761. return "Successful WSASTARTUP not yet performed (WSANOTINITIALISED)";
  762. case WSAEREMOTE:
  763. return "Too many levels of remote in path (WSAEREMOTE)";
  764. case WSAHOST_NOT_FOUND:
  765. return "Host not found (WSAHOST_NOT_FOUND)";
  766. default:
  767. break;
  768. }
  769. #endif
  770. /* format a windows error message */
  771. {
  772. char message[256];
  773. struct buffer out = alloc_buf_gc (256, gc);
  774. const int status = FormatMessage (
  775. FORMAT_MESSAGE_IGNORE_INSERTS
  776. | FORMAT_MESSAGE_FROM_SYSTEM
  777. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  778. NULL,
  779. errnum,
  780. 0,
  781. message,
  782. sizeof (message),
  783. NULL);
  784. if (!status)
  785. {
  786. buf_printf (&out, "[Unknown Win32 Error]");
  787. }
  788. else
  789. {
  790. char *cp;
  791. for (cp = message; *cp != '\0'; ++cp)
  792. {
  793. if (*cp == '\n' || *cp == '\r')
  794. *cp = ' ';
  795. }
  796. buf_printf(&out, "%s", message);
  797. }
  798. return BSTR (&out);
  799. }
  800. }
  801. #endif