PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/openvpn/error.c

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