xref: /freebsd/contrib/ntp/libntp/lib/isc/win32/strerror.c (revision d0b2dbfa)
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