1 /* 2 * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2001, 2002 Internet Software Consortium. 4 * 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. 8 * 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. 16 */ 17 18 /* $Id: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */ 19 20 #include <config.h> 21 22 #include <stdio.h> 23 #include <string.h> 24 #include <winsock2.h> 25 26 #include <isc/mutex.h> 27 #include <isc/once.h> 28 #include <isc/print.h> 29 #include <isc/strerror.h> 30 #include <isc/util.h> 31 32 /* 33 * Forward declarations 34 */ 35 36 char * 37 FormatError(int error); 38 39 char * 40 GetWSAErrorMessage(int errval); 41 42 char * 43 NTstrerror(int err, BOOL *bfreebuf); 44 45 /* 46 * We need to do this this way for profiled locks. 47 */ 48 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); 52 } 53 54 /* 55 * This routine needs to free up any buffer allocated by FormatMessage 56 * if that routine gets used. 57 */ 58 59 void 60 isc__strerror(int num, char *buf, size_t size) { 61 char *msg; 62 BOOL freebuf; 63 unsigned int unum = num; 64 static isc_once_t once = ISC_ONCE_INIT; 65 66 REQUIRE(buf != NULL); 67 68 RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); 69 70 LOCK(&isc_strerror_lock); 71 freebuf = FALSE; 72 msg = NTstrerror(num, &freebuf); 73 if (msg != NULL) 74 snprintf(buf, size, "%s", msg); 75 else 76 snprintf(buf, size, "Unknown error: %u", unum); 77 if(freebuf && msg != NULL) { 78 LocalFree(msg); 79 } 80 UNLOCK(&isc_strerror_lock); 81 } 82 83 /* 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. 88 */ 89 char * 90 FormatError(int error) { 91 LPVOID lpMsgBuf = NULL; 92 FormatMessage( 93 FORMAT_MESSAGE_ALLOCATE_BUFFER | 94 FORMAT_MESSAGE_FROM_SYSTEM | 95 FORMAT_MESSAGE_IGNORE_INSERTS, 96 NULL, 97 error, 98 /* Default language */ 99 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 100 (LPTSTR) &lpMsgBuf, 101 0, 102 NULL); 103 104 return (lpMsgBuf); 105 } 106 107 /* 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. 111 */ 112 char * 113 NTstrerror(int err, BOOL *bfreebuf) { 114 char *retmsg = NULL; 115 116 /* Copy the error value first in case of other errors */ 117 DWORD errval = err; 118 119 *bfreebuf = FALSE; 120 121 /* Get the Winsock2 error messages */ 122 if (errval >= WSABASEERR && errval <= (WSABASEERR + 1999)) { 123 retmsg = GetWSAErrorMessage(errval); 124 if (retmsg != NULL) 125 return (retmsg); 126 } 127 /* 128 * If it's not one of the standard Unix error codes, 129 * try a system error message 130 */ 131 if (errval > (DWORD) _sys_nerr) { 132 *bfreebuf = TRUE; 133 return (FormatError(errval)); 134 } else { 135 return (strerror(errval)); 136 } 137 } 138 139 /* 140 * This is a replacement for perror 141 */ 142 void __cdecl 143 NTperror(char *errmsg) { 144 /* Copy the error value first in case of other errors */ 145 int errval = errno; 146 BOOL bfreebuf = FALSE; 147 char *msg; 148 149 msg = NTstrerror(errval, &bfreebuf); 150 fprintf(stderr, "%s: %s\n", errmsg, msg); 151 if(bfreebuf == TRUE) { 152 LocalFree(msg); 153 } 154 155 } 156 157 /* 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. 161 */ 162 char * 163 GetWSAErrorMessage(int errval) { 164 char *msg; 165 166 switch (errval) { 167 168 case WSAEINTR: 169 msg = "Interrupted system call"; 170 break; 171 172 case WSAEBADF: 173 msg = "Bad file number"; 174 break; 175 176 case WSAEACCES: 177 msg = "Permission denied"; 178 break; 179 180 case WSAEFAULT: 181 msg = "Bad address"; 182 break; 183 184 case WSAEINVAL: 185 msg = "Invalid argument"; 186 break; 187 188 case WSAEMFILE: 189 msg = "Too many open sockets"; 190 break; 191 192 case WSAEWOULDBLOCK: 193 msg = "Operation would block"; 194 break; 195 196 case WSAEINPROGRESS: 197 msg = "Operation now in progress"; 198 break; 199 200 case WSAEALREADY: 201 msg = "Operation already in progress"; 202 break; 203 204 case WSAENOTSOCK: 205 msg = "Socket operation on non-socket"; 206 break; 207 208 case WSAEDESTADDRREQ: 209 msg = "Destination address required"; 210 break; 211 212 case WSAEMSGSIZE: 213 msg = "Message too long"; 214 break; 215 216 case WSAEPROTOTYPE: 217 msg = "Protocol wrong type for socket"; 218 break; 219 220 case WSAENOPROTOOPT: 221 msg = "Bad protocol option"; 222 break; 223 224 case WSAEPROTONOSUPPORT: 225 msg = "Protocol not supported"; 226 break; 227 228 case WSAESOCKTNOSUPPORT: 229 msg = "Socket type not supported"; 230 break; 231 232 case WSAEOPNOTSUPP: 233 msg = "Operation not supported on socket"; 234 break; 235 236 case WSAEPFNOSUPPORT: 237 msg = "Protocol family not supported"; 238 break; 239 240 case WSAEAFNOSUPPORT: 241 msg = "Address family not supported"; 242 break; 243 244 case WSAEADDRINUSE: 245 msg = "Address already in use"; 246 break; 247 248 case WSAEADDRNOTAVAIL: 249 msg = "Can't assign requested address"; 250 break; 251 252 case WSAENETDOWN: 253 msg = "Network is down"; 254 break; 255 256 case WSAENETUNREACH: 257 msg = "Network is unreachable"; 258 break; 259 260 case WSAENETRESET: 261 msg = "Net connection reset"; 262 break; 263 264 case WSAECONNABORTED: 265 msg = "Software caused connection abort"; 266 break; 267 268 case WSAECONNRESET: 269 msg = "Connection reset by peer"; 270 break; 271 272 case WSAENOBUFS: 273 msg = "No buffer space available"; 274 break; 275 276 case WSAEISCONN: 277 msg = "Socket is already connected"; 278 break; 279 280 case WSAENOTCONN: 281 msg = "Socket is not connected"; 282 break; 283 284 case WSAESHUTDOWN: 285 msg = "Can't send after socket shutdown"; 286 break; 287 288 case WSAETOOMANYREFS: 289 msg = "Too many references: can't splice"; 290 break; 291 292 case WSAETIMEDOUT: 293 msg = "Connection timed out"; 294 break; 295 296 case WSAECONNREFUSED: 297 msg = "Connection refused"; 298 break; 299 300 case WSAELOOP: 301 msg = "Too many levels of symbolic links"; 302 break; 303 304 case WSAENAMETOOLONG: 305 msg = "File name too long"; 306 break; 307 308 case WSAEHOSTDOWN: 309 msg = "Host is down"; 310 break; 311 312 case WSAEHOSTUNREACH: 313 msg = "No route to host"; 314 break; 315 316 case WSAENOTEMPTY: 317 msg = "Directory not empty"; 318 break; 319 320 case WSAEPROCLIM: 321 msg = "Too many processes"; 322 break; 323 324 case WSAEUSERS: 325 msg = "Too many users"; 326 break; 327 328 case WSAEDQUOT: 329 msg = "Disc quota exceeded"; 330 break; 331 332 case WSAESTALE: 333 msg = "Stale NFS file handle"; 334 break; 335 336 case WSAEREMOTE: 337 msg = "Too many levels of remote in path"; 338 break; 339 340 case WSASYSNOTREADY: 341 msg = "Network system is unavailable"; 342 break; 343 344 case WSAVERNOTSUPPORTED: 345 msg = "Winsock version out of range"; 346 break; 347 348 case WSANOTINITIALISED: 349 msg = "WSAStartup not yet called"; 350 break; 351 352 case WSAEDISCON: 353 msg = "Graceful shutdown in progress"; 354 break; 355 /* 356 case WSAHOST_NOT_FOUND: 357 msg = "Host not found"; 358 break; 359 360 case WSANO_DATA: 361 msg = "No host data of that type was found"; 362 break; 363 */ 364 default: 365 msg = NULL; 366 break; 367 } 368 return (msg); 369 } 370 371 /* 372 * These error messages are more informative about CryptAPI Errors than the 373 * standard error messages 374 */ 375 376 char * 377 GetCryptErrorMessage(int errval) { 378 char *msg; 379 380 switch (errval) { 381 382 case NTE_BAD_FLAGS: 383 msg = "The dwFlags parameter has an illegal value."; 384 break; 385 case NTE_BAD_KEYSET: 386 msg = "The Registry entry for the key container " 387 "could not be opened and may not exist."; 388 break; 389 case NTE_BAD_KEYSET_PARAM: 390 msg = "The pszContainer or pszProvider parameter " 391 "is set to an illegal value."; 392 break; 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."; 397 break; 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."; 402 break; 403 case NTE_EXISTS: 404 msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" 405 " container already exists."; 406 break; 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."; 412 break; 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 " 416 "pszContainer."; 417 break; 418 case NTE_NO_MEMORY: 419 msg = "The CSP ran out of memory during the operation."; 420 break; 421 case NTE_PROV_DLL_NOT_FOUND: 422 msg = "The provider DLL file does not exist or is not on the " 423 "current path."; 424 break; 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 " 431 "Registry usage."; 432 break; 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."; 438 break; 439 case NTE_PROV_TYPE_NOT_DEF: 440 msg = "No Registry entry exists for the provider type " 441 "specified by dwProvType."; 442 break; 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 " 446 "not a valid DLL."; 447 break; 448 case NTE_SIGNATURE_FILE_BAD: 449 msg = "An error occurred while loading the DLL file image, " 450 "prior to verifying its signature."; 451 break; 452 453 default: 454 msg = NULL; 455 break; 456 } 457 return msg; 458 } 459 460