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;
init_lock(void)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
isc__strerror(int num,char * buf,size_t size)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 *
FormatError(int error)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 *
NTstrerror(int err,BOOL * bfreebuf)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
NTperror(char * errmsg)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 *
GetWSAErrorMessage(int errval)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 *
GetCryptErrorMessage(int errval)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