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