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