1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 2001, 2002 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18258945Sroberto/* $Id: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */ 19258945Sroberto 20258945Sroberto#include <config.h> 21258945Sroberto 22258945Sroberto#include <stdio.h> 23258945Sroberto#include <string.h> 24258945Sroberto#include <winsock2.h> 25258945Sroberto 26258945Sroberto#include <isc/mutex.h> 27258945Sroberto#include <isc/once.h> 28258945Sroberto#include <isc/print.h> 29258945Sroberto#include <isc/strerror.h> 30258945Sroberto#include <isc/util.h> 31258945Sroberto 32258945Sroberto/* 33258945Sroberto * Forward declarations 34258945Sroberto */ 35258945Sroberto 36258945Srobertochar * 37258945SrobertoFormatError(int error); 38258945Sroberto 39258945Srobertochar * 40258945SrobertoGetWSAErrorMessage(int errval); 41258945Sroberto 42258945Srobertochar * 43258945SrobertoNTstrerror(int err, BOOL *bfreebuf); 44258945Sroberto 45258945Sroberto/* 46258945Sroberto * We need to do this this way for profiled locks. 47258945Sroberto */ 48258945Sroberto 49258945Srobertostatic isc_mutex_t isc_strerror_lock; 50258945Srobertostatic void init_lock(void) { 51258945Sroberto RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); 52258945Sroberto} 53258945Sroberto 54258945Sroberto/* 55258945Sroberto * This routine needs to free up any buffer allocated by FormatMessage 56258945Sroberto * if that routine gets used. 57258945Sroberto */ 58258945Sroberto 59258945Srobertovoid 60258945Srobertoisc__strerror(int num, char *buf, size_t size) { 61258945Sroberto char *msg; 62258945Sroberto BOOL freebuf; 63258945Sroberto unsigned int unum = num; 64258945Sroberto static isc_once_t once = ISC_ONCE_INIT; 65258945Sroberto 66258945Sroberto REQUIRE(buf != NULL); 67258945Sroberto 68258945Sroberto RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); 69258945Sroberto 70258945Sroberto LOCK(&isc_strerror_lock); 71258945Sroberto freebuf = FALSE; 72258945Sroberto msg = NTstrerror(num, &freebuf); 73258945Sroberto if (msg != NULL) 74258945Sroberto snprintf(buf, size, "%s", msg); 75258945Sroberto else 76258945Sroberto snprintf(buf, size, "Unknown error: %u", unum); 77258945Sroberto if(freebuf && msg != NULL) { 78258945Sroberto LocalFree(msg); 79258945Sroberto } 80258945Sroberto UNLOCK(&isc_strerror_lock); 81258945Sroberto} 82258945Sroberto 83258945Sroberto/* 84258945Sroberto * Note this will cause a memory leak unless the memory allocated here 85258945Sroberto * is freed by calling LocalFree. isc__strerror does this before unlocking. 86258945Sroberto * This only gets called if there is a system type of error and will likely 87258945Sroberto * be an unusual event. 88258945Sroberto */ 89258945Srobertochar * 90258945SrobertoFormatError(int error) { 91258945Sroberto LPVOID lpMsgBuf = NULL; 92258945Sroberto FormatMessage( 93258945Sroberto FORMAT_MESSAGE_ALLOCATE_BUFFER | 94258945Sroberto FORMAT_MESSAGE_FROM_SYSTEM | 95258945Sroberto FORMAT_MESSAGE_IGNORE_INSERTS, 96258945Sroberto NULL, 97258945Sroberto error, 98258945Sroberto /* Default language */ 99258945Sroberto MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 100258945Sroberto (LPTSTR) &lpMsgBuf, 101258945Sroberto 0, 102258945Sroberto NULL); 103258945Sroberto 104258945Sroberto return (lpMsgBuf); 105258945Sroberto} 106258945Sroberto 107258945Sroberto/* 108258945Sroberto * This routine checks the error value and calls the WSA Windows Sockets 109258945Sroberto * Error message function GetWSAErrorMessage below if it's within that range 110258945Sroberto * since those messages are not available in the system error messages. 111258945Sroberto */ 112258945Srobertochar * 113258945SrobertoNTstrerror(int err, BOOL *bfreebuf) { 114258945Sroberto char *retmsg = NULL; 115258945Sroberto 116258945Sroberto /* Copy the error value first in case of other errors */ 117258945Sroberto DWORD errval = err; 118258945Sroberto 119258945Sroberto *bfreebuf = FALSE; 120258945Sroberto 121258945Sroberto /* Get the Winsock2 error messages */ 122258945Sroberto if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) { 123258945Sroberto retmsg = GetWSAErrorMessage(errval); 124258945Sroberto if (retmsg != NULL) 125258945Sroberto return (retmsg); 126258945Sroberto } 127258945Sroberto /* 128258945Sroberto * If it's not one of the standard Unix error codes, 129258945Sroberto * try a system error message 130258945Sroberto */ 131258945Sroberto if (errval > (DWORD) _sys_nerr) { 132258945Sroberto *bfreebuf = TRUE; 133258945Sroberto return (FormatError(errval)); 134258945Sroberto } else { 135258945Sroberto return (strerror(errval)); 136258945Sroberto } 137258945Sroberto} 138258945Sroberto 139258945Sroberto/* 140258945Sroberto * This is a replacement for perror 141258945Sroberto */ 142258945Srobertovoid __cdecl 143258945SrobertoNTperror(char *errmsg) { 144258945Sroberto /* Copy the error value first in case of other errors */ 145258945Sroberto int errval = errno; 146258945Sroberto BOOL bfreebuf = FALSE; 147258945Sroberto char *msg; 148258945Sroberto 149258945Sroberto msg = NTstrerror(errval, &bfreebuf); 150258945Sroberto fprintf(stderr, "%s: %s\n", errmsg, msg); 151258945Sroberto if(bfreebuf == TRUE) { 152258945Sroberto LocalFree(msg); 153258945Sroberto } 154258945Sroberto 155258945Sroberto} 156258945Sroberto 157258945Sroberto/* 158258945Sroberto * Return the error string related to Winsock2 errors. 159258945Sroberto * This function is necessary since FormatMessage knows nothing about them 160258945Sroberto * and there is no function to get them. 161258945Sroberto */ 162258945Srobertochar * 163258945SrobertoGetWSAErrorMessage(int errval) { 164258945Sroberto char *msg; 165258945Sroberto 166258945Sroberto switch (errval) { 167258945Sroberto 168258945Sroberto case WSAEINTR: 169258945Sroberto msg = "Interrupted system call"; 170258945Sroberto break; 171258945Sroberto 172258945Sroberto case WSAEBADF: 173258945Sroberto msg = "Bad file number"; 174258945Sroberto break; 175258945Sroberto 176258945Sroberto case WSAEACCES: 177258945Sroberto msg = "Permission denied"; 178258945Sroberto break; 179258945Sroberto 180258945Sroberto case WSAEFAULT: 181258945Sroberto msg = "Bad address"; 182258945Sroberto break; 183258945Sroberto 184258945Sroberto case WSAEINVAL: 185258945Sroberto msg = "Invalid argument"; 186258945Sroberto break; 187258945Sroberto 188258945Sroberto case WSAEMFILE: 189258945Sroberto msg = "Too many open sockets"; 190258945Sroberto break; 191258945Sroberto 192258945Sroberto case WSAEWOULDBLOCK: 193258945Sroberto msg = "Operation would block"; 194258945Sroberto break; 195258945Sroberto 196258945Sroberto case WSAEINPROGRESS: 197258945Sroberto msg = "Operation now in progress"; 198258945Sroberto break; 199258945Sroberto 200258945Sroberto case WSAEALREADY: 201258945Sroberto msg = "Operation already in progress"; 202258945Sroberto break; 203258945Sroberto 204258945Sroberto case WSAENOTSOCK: 205258945Sroberto msg = "Socket operation on non-socket"; 206258945Sroberto break; 207258945Sroberto 208258945Sroberto case WSAEDESTADDRREQ: 209258945Sroberto msg = "Destination address required"; 210258945Sroberto break; 211258945Sroberto 212258945Sroberto case WSAEMSGSIZE: 213258945Sroberto msg = "Message too long"; 214258945Sroberto break; 215258945Sroberto 216258945Sroberto case WSAEPROTOTYPE: 217258945Sroberto msg = "Protocol wrong type for socket"; 218258945Sroberto break; 219258945Sroberto 220258945Sroberto case WSAENOPROTOOPT: 221258945Sroberto msg = "Bad protocol option"; 222258945Sroberto break; 223258945Sroberto 224258945Sroberto case WSAEPROTONOSUPPORT: 225258945Sroberto msg = "Protocol not supported"; 226258945Sroberto break; 227258945Sroberto 228258945Sroberto case WSAESOCKTNOSUPPORT: 229258945Sroberto msg = "Socket type not supported"; 230258945Sroberto break; 231258945Sroberto 232258945Sroberto case WSAEOPNOTSUPP: 233258945Sroberto msg = "Operation not supported on socket"; 234258945Sroberto break; 235258945Sroberto 236258945Sroberto case WSAEPFNOSUPPORT: 237258945Sroberto msg = "Protocol family not supported"; 238258945Sroberto break; 239258945Sroberto 240258945Sroberto case WSAEAFNOSUPPORT: 241258945Sroberto msg = "Address family not supported"; 242258945Sroberto break; 243258945Sroberto 244258945Sroberto case WSAEADDRINUSE: 245258945Sroberto msg = "Address already in use"; 246258945Sroberto break; 247258945Sroberto 248258945Sroberto case WSAEADDRNOTAVAIL: 249258945Sroberto msg = "Can't assign requested address"; 250258945Sroberto break; 251258945Sroberto 252258945Sroberto case WSAENETDOWN: 253258945Sroberto msg = "Network is down"; 254258945Sroberto break; 255258945Sroberto 256258945Sroberto case WSAENETUNREACH: 257258945Sroberto msg = "Network is unreachable"; 258258945Sroberto break; 259258945Sroberto 260258945Sroberto case WSAENETRESET: 261258945Sroberto msg = "Net connection reset"; 262258945Sroberto break; 263258945Sroberto 264258945Sroberto case WSAECONNABORTED: 265258945Sroberto msg = "Software caused connection abort"; 266258945Sroberto break; 267258945Sroberto 268258945Sroberto case WSAECONNRESET: 269258945Sroberto msg = "Connection reset by peer"; 270258945Sroberto break; 271258945Sroberto 272258945Sroberto case WSAENOBUFS: 273258945Sroberto msg = "No buffer space available"; 274258945Sroberto break; 275258945Sroberto 276258945Sroberto case WSAEISCONN: 277258945Sroberto msg = "Socket is already connected"; 278258945Sroberto break; 279258945Sroberto 280258945Sroberto case WSAENOTCONN: 281258945Sroberto msg = "Socket is not connected"; 282258945Sroberto break; 283258945Sroberto 284258945Sroberto case WSAESHUTDOWN: 285258945Sroberto msg = "Can't send after socket shutdown"; 286258945Sroberto break; 287258945Sroberto 288258945Sroberto case WSAETOOMANYREFS: 289258945Sroberto msg = "Too many references: can't splice"; 290258945Sroberto break; 291258945Sroberto 292258945Sroberto case WSAETIMEDOUT: 293258945Sroberto msg = "Connection timed out"; 294258945Sroberto break; 295258945Sroberto 296258945Sroberto case WSAECONNREFUSED: 297258945Sroberto msg = "Connection refused"; 298258945Sroberto break; 299258945Sroberto 300258945Sroberto case WSAELOOP: 301258945Sroberto msg = "Too many levels of symbolic links"; 302258945Sroberto break; 303258945Sroberto 304258945Sroberto case WSAENAMETOOLONG: 305258945Sroberto msg = "File name too long"; 306258945Sroberto break; 307258945Sroberto 308258945Sroberto case WSAEHOSTDOWN: 309258945Sroberto msg = "Host is down"; 310258945Sroberto break; 311258945Sroberto 312258945Sroberto case WSAEHOSTUNREACH: 313258945Sroberto msg = "No route to host"; 314258945Sroberto break; 315258945Sroberto 316258945Sroberto case WSAENOTEMPTY: 317258945Sroberto msg = "Directory not empty"; 318258945Sroberto break; 319258945Sroberto 320258945Sroberto case WSAEPROCLIM: 321258945Sroberto msg = "Too many processes"; 322258945Sroberto break; 323258945Sroberto 324258945Sroberto case WSAEUSERS: 325258945Sroberto msg = "Too many users"; 326258945Sroberto break; 327258945Sroberto 328258945Sroberto case WSAEDQUOT: 329258945Sroberto msg = "Disc quota exceeded"; 330258945Sroberto break; 331258945Sroberto 332258945Sroberto case WSAESTALE: 333258945Sroberto msg = "Stale NFS file handle"; 334258945Sroberto break; 335258945Sroberto 336258945Sroberto case WSAEREMOTE: 337258945Sroberto msg = "Too many levels of remote in path"; 338258945Sroberto break; 339258945Sroberto 340258945Sroberto case WSASYSNOTREADY: 341258945Sroberto msg = "Network system is unavailable"; 342258945Sroberto break; 343258945Sroberto 344258945Sroberto case WSAVERNOTSUPPORTED: 345258945Sroberto msg = "Winsock version out of range"; 346258945Sroberto break; 347258945Sroberto 348258945Sroberto case WSANOTINITIALISED: 349258945Sroberto msg = "WSAStartup not yet called"; 350258945Sroberto break; 351258945Sroberto 352258945Sroberto case WSAEDISCON: 353258945Sroberto msg = "Graceful shutdown in progress"; 354258945Sroberto break; 355258945Sroberto/* 356258945Sroberto case WSAHOST_NOT_FOUND: 357258945Sroberto msg = "Host not found"; 358258945Sroberto break; 359258945Sroberto 360258945Sroberto case WSANO_DATA: 361258945Sroberto msg = "No host data of that type was found"; 362258945Sroberto break; 363258945Sroberto*/ 364258945Sroberto default: 365258945Sroberto msg = NULL; 366258945Sroberto break; 367258945Sroberto } 368258945Sroberto return (msg); 369258945Sroberto} 370258945Sroberto 371258945Sroberto/* 372258945Sroberto * These error messages are more informative about CryptAPI Errors than the 373258945Sroberto * standard error messages 374258945Sroberto */ 375258945Sroberto 376258945Srobertochar * 377258945SrobertoGetCryptErrorMessage(int errval) { 378258945Sroberto char *msg; 379258945Sroberto 380258945Sroberto switch (errval) { 381258945Sroberto 382258945Sroberto case NTE_BAD_FLAGS: 383258945Sroberto msg = "The dwFlags parameter has an illegal value."; 384258945Sroberto break; 385258945Sroberto case NTE_BAD_KEYSET: 386258945Sroberto msg = "The Registry entry for the key container " 387258945Sroberto "could not be opened and may not exist."; 388258945Sroberto break; 389258945Sroberto case NTE_BAD_KEYSET_PARAM: 390258945Sroberto msg = "The pszContainer or pszProvider parameter " 391258945Sroberto "is set to an illegal value."; 392258945Sroberto break; 393258945Sroberto case NTE_BAD_PROV_TYPE: 394258945Sroberto msg = "The value of the dwProvType parameter is out " 395258945Sroberto "of range. All provider types must be from " 396258945Sroberto "1 to 999, inclusive."; 397258945Sroberto break; 398258945Sroberto case NTE_BAD_SIGNATURE: 399258945Sroberto msg = "The provider DLL signature did not verify " 400258945Sroberto "correctly. Either the DLL or the digital " 401258945Sroberto "signature has been tampered with."; 402258945Sroberto break; 403258945Sroberto case NTE_EXISTS: 404258945Sroberto msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" 405258945Sroberto " container already exists."; 406258945Sroberto break; 407258945Sroberto case NTE_KEYSET_ENTRY_BAD: 408258945Sroberto msg = "The Registry entry for the pszContainer key container " 409258945Sroberto "was found (in the HKEY_CURRENT_USER window), but is " 410258945Sroberto "corrupt. See the section System Administration for " 411258945Sroberto " etails about CryptoAPI's Registry usage."; 412258945Sroberto break; 413258945Sroberto case NTE_KEYSET_NOT_DEF: 414258945Sroberto msg = "No Registry entry exists in the HKEY_CURRENT_USER " 415258945Sroberto "window for the key container specified by " 416258945Sroberto "pszContainer."; 417258945Sroberto break; 418258945Sroberto case NTE_NO_MEMORY: 419258945Sroberto msg = "The CSP ran out of memory during the operation."; 420258945Sroberto break; 421258945Sroberto case NTE_PROV_DLL_NOT_FOUND: 422258945Sroberto msg = "The provider DLL file does not exist or is not on the " 423258945Sroberto "current path."; 424258945Sroberto break; 425258945Sroberto case NTE_PROV_TYPE_ENTRY_BAD: 426258945Sroberto msg = "The Registry entry for the provider type specified by " 427258945Sroberto "dwProvType is corrupt. This error may relate to " 428258945Sroberto "either the user default CSP list or the machine " 429258945Sroberto "default CSP list. See the section System " 430258945Sroberto "Administration for details about CryptoAPI's " 431258945Sroberto "Registry usage."; 432258945Sroberto break; 433258945Sroberto case NTE_PROV_TYPE_NO_MATCH: 434258945Sroberto msg = "The provider type specified by dwProvType does not " 435258945Sroberto "match the provider type found in the Registry. Note " 436258945Sroberto "that this error can only occur when pszProvider " 437258945Sroberto "specifies an actual CSP name."; 438258945Sroberto break; 439258945Sroberto case NTE_PROV_TYPE_NOT_DEF: 440258945Sroberto msg = "No Registry entry exists for the provider type " 441258945Sroberto "specified by dwProvType."; 442258945Sroberto break; 443258945Sroberto case NTE_PROVIDER_DLL_FAIL: 444258945Sroberto msg = "The provider DLL file could not be loaded, and " 445258945Sroberto "may not exist. If it exists, then the file is " 446258945Sroberto "not a valid DLL."; 447258945Sroberto break; 448258945Sroberto case NTE_SIGNATURE_FILE_BAD: 449258945Sroberto msg = "An error occurred while loading the DLL file image, " 450258945Sroberto "prior to verifying its signature."; 451258945Sroberto break; 452258945Sroberto 453258945Sroberto default: 454258945Sroberto msg = NULL; 455258945Sroberto break; 456258945Sroberto } 457258945Sroberto return msg; 458258945Sroberto} 459258945Sroberto 460