2 * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001, 2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
26 #include <isc/mutex.h>
28 #include <isc/print.h>
29 #include <isc/strerror.h>
33 * Forward declarations
37 FormatError(int error);
40 GetWSAErrorMessage(int errval);
43 NTstrerror(int err, BOOL *bfreebuf);
46 * We need to do this this way for profiled locks.
49 static isc_mutex_t isc_strerror_lock;
50 static void init_lock(void) {
51 RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
55 * This routine needs to free up any buffer allocated by FormatMessage
56 * if that routine gets used.
60 isc__strerror(int num, char *buf, size_t size) {
63 unsigned int unum = num;
64 static isc_once_t once = ISC_ONCE_INIT;
68 RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
70 LOCK(&isc_strerror_lock);
72 msg = NTstrerror(num, &freebuf);
74 snprintf(buf, size, "%s", msg);
76 snprintf(buf, size, "Unknown error: %u", unum);
77 if(freebuf && msg != NULL) {
80 UNLOCK(&isc_strerror_lock);
84 * Note this will cause a memory leak unless the memory allocated here
85 * is freed by calling LocalFree. isc__strerror does this before unlocking.
86 * This only gets called if there is a system type of error and will likely
87 * be an unusual event.
90 FormatError(int error) {
91 LPVOID lpMsgBuf = NULL;
93 FORMAT_MESSAGE_ALLOCATE_BUFFER |
94 FORMAT_MESSAGE_FROM_SYSTEM |
95 FORMAT_MESSAGE_IGNORE_INSERTS,
98 /* Default language */
99 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
108 * This routine checks the error value and calls the WSA Windows Sockets
109 * Error message function GetWSAErrorMessage below if it's within that range
110 * since those messages are not available in the system error messages.
113 NTstrerror(int err, BOOL *bfreebuf) {
116 /* Copy the error value first in case of other errors */
121 /* Get the Winsock2 error messages */
122 if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) {
123 retmsg = GetWSAErrorMessage(errval);
128 * If it's not one of the standard Unix error codes,
129 * try a system error message
131 if (errval > (DWORD) _sys_nerr) {
133 return (FormatError(errval));
135 return (strerror(errval));
140 * This is a replacement for perror
143 NTperror(char *errmsg) {
144 /* Copy the error value first in case of other errors */
146 BOOL bfreebuf = FALSE;
149 msg = NTstrerror(errval, &bfreebuf);
150 fprintf(stderr, "%s: %s\n", errmsg, msg);
151 if(bfreebuf == TRUE) {
158 * Return the error string related to Winsock2 errors.
159 * This function is necessary since FormatMessage knows nothing about them
160 * and there is no function to get them.
163 GetWSAErrorMessage(int errval) {
169 msg = "Interrupted system call";
173 msg = "Bad file number";
177 msg = "Permission denied";
185 msg = "Invalid argument";
189 msg = "Too many open sockets";
193 msg = "Operation would block";
197 msg = "Operation now in progress";
201 msg = "Operation already in progress";
205 msg = "Socket operation on non-socket";
208 case WSAEDESTADDRREQ:
209 msg = "Destination address required";
213 msg = "Message too long";
217 msg = "Protocol wrong type for socket";
221 msg = "Bad protocol option";
224 case WSAEPROTONOSUPPORT:
225 msg = "Protocol not supported";
228 case WSAESOCKTNOSUPPORT:
229 msg = "Socket type not supported";
233 msg = "Operation not supported on socket";
236 case WSAEPFNOSUPPORT:
237 msg = "Protocol family not supported";
240 case WSAEAFNOSUPPORT:
241 msg = "Address family not supported";
245 msg = "Address already in use";
248 case WSAEADDRNOTAVAIL:
249 msg = "Can't assign requested address";
253 msg = "Network is down";
257 msg = "Network is unreachable";
261 msg = "Net connection reset";
264 case WSAECONNABORTED:
265 msg = "Software caused connection abort";
269 msg = "Connection reset by peer";
273 msg = "No buffer space available";
277 msg = "Socket is already connected";
281 msg = "Socket is not connected";
285 msg = "Can't send after socket shutdown";
288 case WSAETOOMANYREFS:
289 msg = "Too many references: can't splice";
293 msg = "Connection timed out";
296 case WSAECONNREFUSED:
297 msg = "Connection refused";
301 msg = "Too many levels of symbolic links";
304 case WSAENAMETOOLONG:
305 msg = "File name too long";
309 msg = "Host is down";
312 case WSAEHOSTUNREACH:
313 msg = "No route to host";
317 msg = "Directory not empty";
321 msg = "Too many processes";
325 msg = "Too many users";
329 msg = "Disc quota exceeded";
333 msg = "Stale NFS file handle";
337 msg = "Too many levels of remote in path";
341 msg = "Network system is unavailable";
344 case WSAVERNOTSUPPORTED:
345 msg = "Winsock version out of range";
348 case WSANOTINITIALISED:
349 msg = "WSAStartup not yet called";
353 msg = "Graceful shutdown in progress";
356 case WSAHOST_NOT_FOUND:
357 msg = "Host not found";
361 msg = "No host data of that type was found";
372 * These error messages are more informative about CryptAPI Errors than the
373 * standard error messages
377 GetCryptErrorMessage(int errval) {
383 msg = "The dwFlags parameter has an illegal value.";
386 msg = "The Registry entry for the key container "
387 "could not be opened and may not exist.";
389 case NTE_BAD_KEYSET_PARAM:
390 msg = "The pszContainer or pszProvider parameter "
391 "is set to an illegal value.";
393 case NTE_BAD_PROV_TYPE:
394 msg = "The value of the dwProvType parameter is out "
395 "of range. All provider types must be from "
396 "1 to 999, inclusive.";
398 case NTE_BAD_SIGNATURE:
399 msg = "The provider DLL signature did not verify "
400 "correctly. Either the DLL or the digital "
401 "signature has been tampered with.";
404 msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key"
405 " container already exists.";
407 case NTE_KEYSET_ENTRY_BAD:
408 msg = "The Registry entry for the pszContainer key container "
409 "was found (in the HKEY_CURRENT_USER window), but is "
410 "corrupt. See the section System Administration for "
411 " etails about CryptoAPI's Registry usage.";
413 case NTE_KEYSET_NOT_DEF:
414 msg = "No Registry entry exists in the HKEY_CURRENT_USER "
415 "window for the key container specified by "
419 msg = "The CSP ran out of memory during the operation.";
421 case NTE_PROV_DLL_NOT_FOUND:
422 msg = "The provider DLL file does not exist or is not on the "
425 case NTE_PROV_TYPE_ENTRY_BAD:
426 msg = "The Registry entry for the provider type specified by "
427 "dwProvType is corrupt. This error may relate to "
428 "either the user default CSP list or the machine "
429 "default CSP list. See the section System "
430 "Administration for details about CryptoAPI's "
433 case NTE_PROV_TYPE_NO_MATCH:
434 msg = "The provider type specified by dwProvType does not "
435 "match the provider type found in the Registry. Note "
436 "that this error can only occur when pszProvider "
437 "specifies an actual CSP name.";
439 case NTE_PROV_TYPE_NOT_DEF:
440 msg = "No Registry entry exists for the provider type "
441 "specified by dwProvType.";
443 case NTE_PROVIDER_DLL_FAIL:
444 msg = "The provider DLL file could not be loaded, and "
445 "may not exist. If it exists, then the file is "
448 case NTE_SIGNATURE_FILE_BAD:
449 msg = "An error occurred while loading the DLL file image, "
450 "prior to verifying its signature.";