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 #include "lib_strbuf.h" 33 34 /* 35 * Forward declarations 36 */ 37 38 char * 39 FormatError(int error); 40 41 char * 42 GetWSAErrorMessage(int errval); 43 44 char * 45 NTstrerror(int err, BOOL *bfreebuf); 46 47 /* 48 * We need to do this this way for profiled locks. 49 */ 50 51 static isc_mutex_t isc_strerror_lock; 52 static void init_lock(void) { 53 RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); 54 } 55 56 /* 57 * This routine needs to free up any buffer allocated by FormatMessage 58 * if that routine gets used. 59 */ 60 61 void 62 isc__strerror(int num, char *buf, size_t size) { 63 char *msg; 64 BOOL freebuf; 65 unsigned int unum = num; 66 static isc_once_t once = ISC_ONCE_INIT; 67 68 REQUIRE(buf != NULL); 69 70 RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); 71 72 LOCK(&isc_strerror_lock); 73 freebuf = FALSE; 74 msg = NTstrerror(num, &freebuf); 75 if (msg != NULL) 76 snprintf(buf, size, "%s", msg); 77 else 78 snprintf(buf, size, "Unknown error: %u", unum); 79 if(freebuf && msg != NULL) { 80 LocalFree(msg); 81 } 82 UNLOCK(&isc_strerror_lock); 83 } 84 85 /* 86 * Note this will cause a memory leak unless the memory allocated here 87 * is freed by calling LocalFree. isc__strerror does this before unlocking. 88 * This only gets called if there is a system type of error and will likely 89 * be an unusual event. 90 */ 91 char * 92 FormatError(int error) { 93 char *lpMsgBuf = NULL; 94 char *pch; 95 const char boiler[] = 96 " For information about network troubleshooting, see Windows Help."; 97 size_t last; 98 99 FormatMessage( 100 FORMAT_MESSAGE_ALLOCATE_BUFFER | 101 FORMAT_MESSAGE_FROM_SYSTEM | 102 (FORMAT_MESSAGE_MAX_WIDTH_MASK - 1), 103 NULL, 104 error, 105 /* Default language */ 106 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 107 (LPTSTR)(PVOID)&lpMsgBuf, 108 0, 109 NULL); 110 111 /* remove useless boilerplate */ 112 pch = strstr(lpMsgBuf, boiler); 113 if (pch != NULL) { 114 *pch = '\0'; 115 } 116 117 /* strip any trailing CR/LF and spaces */ 118 if (lpMsgBuf != NULL) { 119 last = strlen(lpMsgBuf); 120 if (last > 0) { 121 --last; 122 } 123 while ('\n' == lpMsgBuf[last] || 124 '\r' == lpMsgBuf[last] || 125 ' ' == lpMsgBuf[last]) { 126 127 lpMsgBuf[last] = '\0'; 128 if (last > 0) { 129 --last; 130 } 131 } 132 } 133 134 return (lpMsgBuf); 135 } 136 137 /* 138 * This routine checks the error value and calls the WSA Windows Sockets 139 * Error message function GetWSAErrorMessage below if it's within that range 140 * since those messages are not available in the system error messages. 141 */ 142 char * 143 NTstrerror(int err, BOOL *bfreebuf) { 144 char *retmsg = NULL; 145 146 *bfreebuf = FALSE; 147 148 /* Get the Winsock2 error messages */ 149 /* DLH this may not be needed, FormatError/FormatMessage may handle Winsock error codes */ 150 if (err >= WSABASEERR && err <= (WSABASEERR + 1999)) { 151 retmsg = GetWSAErrorMessage(err); 152 } 153 /* 154 * If it's not one of the standard Unix error codes, 155 * try a system error message 156 */ 157 if (NULL == retmsg) { 158 if (err > _sys_nerr) { 159 *bfreebuf = TRUE; 160 retmsg = FormatError(err); 161 } else { 162 retmsg = lib_getbuf(); 163 if (0 != strerror_s(retmsg, LIB_BUFLENGTH, err)) { 164 snprintf(retmsg, LIB_BUFLENGTH, 165 "Unknown error number %d/0x%x", 166 err, err); 167 } 168 } 169 } 170 return retmsg; 171 } 172 173 /* 174 * This is a replacement for perror 175 */ 176 void __cdecl 177 NTperror(char *errmsg) { 178 /* Copy the error value first in case of other errors */ 179 int errval = errno; 180 BOOL bfreebuf = FALSE; 181 char *msg; 182 183 msg = NTstrerror(errval, &bfreebuf); 184 fprintf(stderr, "%s: %s\n", errmsg, msg); 185 if(bfreebuf == TRUE) { 186 LocalFree(msg); 187 } 188 189 } 190 191 /* 192 * Return the error string related to Winsock2 errors. 193 * This function is necessary since FormatMessage knows nothing about them 194 * and there is no function to get them. 195 */ 196 char * 197 GetWSAErrorMessage(int errval) { 198 char *msg; 199 200 switch (errval) { 201 202 case WSAEINTR: 203 msg = "Interrupted system call"; 204 break; 205 206 case WSAEBADF: 207 msg = "Bad file number"; 208 break; 209 210 case WSAEACCES: 211 msg = "Permission denied"; 212 break; 213 214 case WSAEFAULT: 215 msg = "Bad address"; 216 break; 217 218 case WSAEINVAL: 219 msg = "Invalid argument"; 220 break; 221 222 case WSAEMFILE: 223 msg = "Too many open sockets"; 224 break; 225 226 case WSAEWOULDBLOCK: 227 msg = "Operation would block"; 228 break; 229 230 case WSAEINPROGRESS: 231 msg = "Operation now in progress"; 232 break; 233 234 case WSAEALREADY: 235 msg = "Operation already in progress"; 236 break; 237 238 case WSAENOTSOCK: 239 msg = "Socket operation on non-socket"; 240 break; 241 242 case WSAEDESTADDRREQ: 243 msg = "Destination address required"; 244 break; 245 246 case WSAEMSGSIZE: 247 msg = "Message too long"; 248 break; 249 250 case WSAEPROTOTYPE: 251 msg = "Protocol wrong type for socket"; 252 break; 253 254 case WSAENOPROTOOPT: 255 msg = "Bad protocol option"; 256 break; 257 258 case WSAEPROTONOSUPPORT: 259 msg = "Protocol not supported"; 260 break; 261 262 case WSAESOCKTNOSUPPORT: 263 msg = "Socket type not supported"; 264 break; 265 266 case WSAEOPNOTSUPP: 267 msg = "Operation not supported on socket"; 268 break; 269 270 case WSAEPFNOSUPPORT: 271 msg = "Protocol family not supported"; 272 break; 273 274 case WSAEAFNOSUPPORT: 275 msg = "Address family not supported"; 276 break; 277 278 case WSAEADDRINUSE: 279 msg = "Address already in use"; 280 break; 281 282 case WSAEADDRNOTAVAIL: 283 msg = "Can't assign requested address"; 284 break; 285 286 case WSAENETDOWN: 287 msg = "Network is down"; 288 break; 289 290 case WSAENETUNREACH: 291 msg = "Network is unreachable"; 292 break; 293 294 case WSAENETRESET: 295 msg = "Net connection reset"; 296 break; 297 298 case WSAECONNABORTED: 299 msg = "Software caused connection abort"; 300 break; 301 302 case WSAECONNRESET: 303 msg = "Connection reset by peer"; 304 break; 305 306 case WSAENOBUFS: 307 msg = "No buffer space available"; 308 break; 309 310 case WSAEISCONN: 311 msg = "Socket is already connected"; 312 break; 313 314 case WSAENOTCONN: 315 msg = "Socket is not connected"; 316 break; 317 318 case WSAESHUTDOWN: 319 msg = "Can't send after socket shutdown"; 320 break; 321 322 case WSAETOOMANYREFS: 323 msg = "Too many references: can't splice"; 324 break; 325 326 case WSAETIMEDOUT: 327 msg = "Connection timed out"; 328 break; 329 330 case WSAECONNREFUSED: 331 msg = "Connection refused"; 332 break; 333 334 case WSAELOOP: 335 msg = "Too many levels of symbolic links"; 336 break; 337 338 case WSAENAMETOOLONG: 339 msg = "File name too long"; 340 break; 341 342 case WSAEHOSTDOWN: 343 msg = "Host is down"; 344 break; 345 346 case WSAEHOSTUNREACH: 347 msg = "No route to host"; 348 break; 349 350 case WSAENOTEMPTY: 351 msg = "Directory not empty"; 352 break; 353 354 case WSAEPROCLIM: 355 msg = "Too many processes"; 356 break; 357 358 case WSAEUSERS: 359 msg = "Too many users"; 360 break; 361 362 case WSAEDQUOT: 363 msg = "Disc quota exceeded"; 364 break; 365 366 case WSAESTALE: 367 msg = "Stale NFS file handle"; 368 break; 369 370 case WSAEREMOTE: 371 msg = "Too many levels of remote in path"; 372 break; 373 374 case WSASYSNOTREADY: 375 msg = "Network system is unavailable"; 376 break; 377 378 case WSAVERNOTSUPPORTED: 379 msg = "Winsock version out of range"; 380 break; 381 382 case WSANOTINITIALISED: 383 msg = "WSAStartup not yet called"; 384 break; 385 386 case WSAEDISCON: 387 msg = "Graceful shutdown in progress"; 388 break; 389 /* 390 case WSAHOST_NOT_FOUND: 391 msg = "Host not found"; 392 break; 393 394 case WSANO_DATA: 395 msg = "No host data of that type was found"; 396 break; 397 */ 398 default: 399 msg = NULL; 400 break; 401 } 402 return (msg); 403 } 404 405 /* 406 * These error messages are more informative about CryptAPI Errors than the 407 * standard error messages 408 */ 409 410 char * 411 GetCryptErrorMessage(int errval) { 412 char *msg; 413 414 switch (errval) { 415 416 case NTE_BAD_FLAGS: 417 msg = "The dwFlags parameter has an illegal value."; 418 break; 419 case NTE_BAD_KEYSET: 420 msg = "The Registry entry for the key container " 421 "could not be opened and may not exist."; 422 break; 423 case NTE_BAD_KEYSET_PARAM: 424 msg = "The pszContainer or pszProvider parameter " 425 "is set to an illegal value."; 426 break; 427 case NTE_BAD_PROV_TYPE: 428 msg = "The value of the dwProvType parameter is out " 429 "of range. All provider types must be from " 430 "1 to 999, inclusive."; 431 break; 432 case NTE_BAD_SIGNATURE: 433 msg = "The provider DLL signature did not verify " 434 "correctly. Either the DLL or the digital " 435 "signature has been tampered with."; 436 break; 437 case NTE_EXISTS: 438 msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" 439 " container already exists."; 440 break; 441 case NTE_KEYSET_ENTRY_BAD: 442 msg = "The Registry entry for the pszContainer key container " 443 "was found (in the HKEY_CURRENT_USER window), but is " 444 "corrupt. See the section System Administration for " 445 " etails about CryptoAPI's Registry usage."; 446 break; 447 case NTE_KEYSET_NOT_DEF: 448 msg = "No Registry entry exists in the HKEY_CURRENT_USER " 449 "window for the key container specified by " 450 "pszContainer."; 451 break; 452 case NTE_NO_MEMORY: 453 msg = "The CSP ran out of memory during the operation."; 454 break; 455 case NTE_PROV_DLL_NOT_FOUND: 456 msg = "The provider DLL file does not exist or is not on the " 457 "current path."; 458 break; 459 case NTE_PROV_TYPE_ENTRY_BAD: 460 msg = "The Registry entry for the provider type specified by " 461 "dwProvType is corrupt. This error may relate to " 462 "either the user default CSP list or the machine " 463 "default CSP list. See the section System " 464 "Administration for details about CryptoAPI's " 465 "Registry usage."; 466 break; 467 case NTE_PROV_TYPE_NO_MATCH: 468 msg = "The provider type specified by dwProvType does not " 469 "match the provider type found in the Registry. Note " 470 "that this error can only occur when pszProvider " 471 "specifies an actual CSP name."; 472 break; 473 case NTE_PROV_TYPE_NOT_DEF: 474 msg = "No Registry entry exists for the provider type " 475 "specified by dwProvType."; 476 break; 477 case NTE_PROVIDER_DLL_FAIL: 478 msg = "The provider DLL file could not be loaded, and " 479 "may not exist. If it exists, then the file is " 480 "not a valid DLL."; 481 break; 482 case NTE_SIGNATURE_FILE_BAD: 483 msg = "An error occurred while loading the DLL file image, " 484 "prior to verifying its signature."; 485 break; 486 487 default: 488 msg = NULL; 489 break; 490 } 491 return msg; 492 } 493 494