bsm_errno.c revision 186647
1/*-
2 * Copyright (c) 2008 Apple Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_errno.c#12
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/security/audit/audit_bsm_errno.c 186647 2008-12-31 11:12:24Z rwatson $");
34
35#include <sys/types.h>
36
37#include <bsm/audit_errno.h>
38#include <bsm/libbsm.h>
39
40#include <sys/errno.h>
41
42/*
43 * Different operating systems use different numeric constants for different
44 * error numbers, and sometimes error numbers don't exist in more than one
45 * operating system.  These routines convert between BSM and local error
46 * number spaces, subject to the above realities.  BSM error numbers are
47 * stored in a single 8-bit character, so don't have a byte order.
48 */
49
50struct bsm_errors {
51	int		 be_bsm_error;
52	int		 be_os_error;
53	const char	*be_strerror;
54};
55
56#define	ERRNO_NO_LOCAL_MAPPING	-600
57
58/*
59 * Mapping table -- please maintain in numeric sorted order with respect to
60 * the BSM constant.  Today we do a linear lookup, but could switch to a
61 * binary search if it makes sense.  We only ifdef errors that aren't
62 * generally available, but it does make the table a lot more ugly.
63 *
64 * XXXRW: It would be nice to have a similar ordered table mapping to BSM
65 * constant from local constant, but the order of local constants varies by
66 * OS.  Really we need to build that table at compile-time but don't do that
67 * yet.
68 *
69 * XXXRW: We currently embed English-language error strings here, but should
70 * support catalogues; these are only used if the OS doesn't have an error
71 * string using strerror(3).
72 */
73static const struct bsm_errors bsm_errors[] = {
74	{ BSM_ESUCCESS, 0, "Success" },
75	{ BSM_EPERM, EPERM, "Operation not permitted" },
76	{ BSM_ENOENT, ENOENT, "No such file or directory" },
77	{ BSM_ESRCH, ESRCH, "No such process" },
78	{ BSM_EINTR, EINTR, "Interrupted system call" },
79	{ BSM_EIO, EIO, "Input/output error" },
80	{ BSM_ENXIO, ENXIO, "Device not configured" },
81	{ BSM_E2BIG, E2BIG, "Argument list too long" },
82	{ BSM_ENOEXEC, ENOEXEC, "Exec format error" },
83	{ BSM_EBADF, EBADF, "BAd file descriptor" },
84	{ BSM_ECHILD, ECHILD, "No child processes" },
85	{ BSM_EAGAIN, EAGAIN, "Resource temporarily unavailable" },
86	{ BSM_ENOMEM, ENOMEM, "Cannot allocate memory" },
87	{ BSM_EACCES, EACCES, "Permission denied" },
88	{ BSM_EFAULT, EFAULT, "Bad address" },
89	{ BSM_ENOTBLK, ENOTBLK, "Block device required" },
90	{ BSM_EBUSY, EBUSY, "Device busy" },
91	{ BSM_EEXIST, EEXIST, "File exists" },
92	{ BSM_EXDEV, EXDEV, "Cross-device link" },
93	{ BSM_ENODEV, ENODEV, "Operation not supported by device" },
94	{ BSM_ENOTDIR, ENOTDIR, "Not a directory" },
95	{ BSM_EISDIR, EISDIR, "Is a directory" },
96	{ BSM_EINVAL, EINVAL, "Invalid argument" },
97	{ BSM_ENFILE, ENFILE, "Too many open files in system" },
98	{ BSM_EMFILE, EMFILE, "Too many open files" },
99	{ BSM_ENOTTY, ENOTTY, "Inappropriate ioctl for device" },
100	{ BSM_ETXTBSY, ETXTBSY, "Text file busy" },
101	{ BSM_EFBIG, EFBIG, "File too large" },
102	{ BSM_ENOSPC, ENOSPC, "No space left on device" },
103	{ BSM_ESPIPE, ESPIPE, "Illegal seek" },
104	{ BSM_EROFS, EROFS, "Read-only file system" },
105	{ BSM_EMLINK, EMLINK, "Too many links" },
106	{ BSM_EPIPE, EPIPE, "Broken pipe" },
107	{ BSM_EDOM, EDOM, "Numerical argument out of domain" },
108	{ BSM_ERANGE, ERANGE, "Result too large" },
109	{ BSM_ENOMSG, ENOMSG, "No message of desired type" },
110	{ BSM_EIDRM, EIDRM, "Identifier removed" },
111	{ BSM_ECHRNG,
112#ifdef ECHRNG
113	ECHRNG,
114#else
115	ERRNO_NO_LOCAL_MAPPING,
116#endif
117	"Channel number out of range" },
118	{ BSM_EL2NSYNC,
119#ifdef EL2NSYNC
120	EL2NSYNC,
121#else
122	ERRNO_NO_LOCAL_MAPPING,
123#endif
124	"Level 2 not synchronized" },
125	{ BSM_EL3HLT,
126#ifdef EL3HLT
127	EL3HLT,
128#else
129	ERRNO_NO_LOCAL_MAPPING,
130#endif
131	"Level 3 halted" },
132	{ BSM_EL3RST,
133#ifdef EL3RST
134	EL3RST,
135#else
136	ERRNO_NO_LOCAL_MAPPING,
137#endif
138	"Level 3 reset" },
139	{ BSM_ELNRNG,
140#ifdef ELNRNG
141	ELNRNG,
142#else
143	ERRNO_NO_LOCAL_MAPPING,
144#endif
145	"Link number out of range" },
146	{ BSM_EUNATCH,
147#ifdef EUNATCH
148	EUNATCH,
149#else
150	ERRNO_NO_LOCAL_MAPPING,
151#endif
152	"Protocol driver not attached" },
153	{ BSM_ENOCSI,
154#ifdef ENOCSI
155	ENOCSI,
156#else
157	ERRNO_NO_LOCAL_MAPPING,
158#endif
159	"No CSI structure available" },
160	{ BSM_EL2HLT,
161#ifdef EL2HLT
162	EL2HLT,
163#else
164	ERRNO_NO_LOCAL_MAPPING,
165#endif
166	"Level 2 halted" },
167	{ BSM_EDEADLK, EDEADLK, "Resource deadlock avoided" },
168	{ BSM_ENOLCK, ENOLCK, "No locks available" },
169	{ BSM_ECANCELED, ECANCELED, "Operation canceled" },
170	{ BSM_ENOTSUP, ENOTSUP, "Operation not supported" },
171	{ BSM_EDQUOT, EDQUOT, "Disc quota exceeded" },
172	{ BSM_EBADE,
173#ifdef EBADE
174	EBADE,
175#else
176	ERRNO_NO_LOCAL_MAPPING,
177#endif
178	"Invalid exchange" },
179	{ BSM_EBADR,
180#ifdef EBADR
181	EBADR,
182#else
183	ERRNO_NO_LOCAL_MAPPING,
184#endif
185	"Invalid request descriptor" },
186	{ BSM_EXFULL,
187#ifdef EXFULL
188	EXFULL,
189#else
190	ERRNO_NO_LOCAL_MAPPING,
191#endif
192	"Exchange full" },
193	{ BSM_ENOANO,
194#ifdef ENOANO
195	ENOANO,
196#else
197	ERRNO_NO_LOCAL_MAPPING,
198#endif
199	"No anode" },
200	{ BSM_EBADRQC,
201#ifdef EBADRQC
202	EBADRQC,
203#else
204	ERRNO_NO_LOCAL_MAPPING,
205#endif
206	"Invalid request descriptor" },
207	{ BSM_EBADSLT,
208#ifdef EBADSLT
209	EBADSLT,
210#else
211	ERRNO_NO_LOCAL_MAPPING,
212#endif
213	"Invalid slot" },
214	{ BSM_EDEADLOCK,
215#ifdef EDEADLOCK
216	EDEADLOCK,
217#else
218	ERRNO_NO_LOCAL_MAPPING,
219#endif
220	"Resource deadlock avoided" },
221	{ BSM_EBFONT,
222#ifdef EBFONT
223	EBFONT,
224#else
225	ERRNO_NO_LOCAL_MAPPING,
226#endif
227	"Bad font file format" },
228	{ BSM_EOWNERDEAD,
229#ifdef EOWNERDEAD
230	EOWNERDEAD,
231#else
232	ERRNO_NO_LOCAL_MAPPING,
233#endif
234	"Process died with the lock" },
235	{ BSM_ENOTRECOVERABLE,
236#ifdef ENOTRECOVERABLE
237	ENOTRECOVERABLE,
238#else
239	ERRNO_NO_LOCAL_MAPPING,
240#endif
241	"Lock is not recoverable" },
242	{ BSM_ENOSTR,
243#ifdef ENOSTR
244	ENOSTR,
245#else
246	ERRNO_NO_LOCAL_MAPPING,
247#endif
248	"Device not a stream" },
249	{ BSM_ENONET,
250#ifdef ENONET
251	ENONET,
252#else
253	ERRNO_NO_LOCAL_MAPPING,
254#endif
255	"Machine is not on the network" },
256	{ BSM_ENOPKG,
257#ifdef ENOPKG
258	ENOPKG,
259#else
260	ERRNO_NO_LOCAL_MAPPING,
261#endif
262	"Package not installed" },
263	{ BSM_EREMOTE, EREMOTE, "Too many levels of remote in path" },
264	{ BSM_ENOLINK,
265#ifdef ENOLINK
266	ENOLINK,
267#else
268	ERRNO_NO_LOCAL_MAPPING,
269#endif
270	"Link has been severed" },
271	{ BSM_EADV,
272#ifdef EADV
273	EADV,
274#else
275	ERRNO_NO_LOCAL_MAPPING,
276#endif
277	"Advertise error" },
278	{ BSM_ESRMNT,
279#ifdef ESRMNT
280	ESRMNT,
281#else
282	ERRNO_NO_LOCAL_MAPPING,
283#endif
284	"srmount error" },
285	{ BSM_ECOMM,
286#ifdef ECOMM
287	ECOMM,
288#else
289	ERRNO_NO_LOCAL_MAPPING,
290#endif
291	"Communication error on send" },
292	{ BSM_EPROTO,
293#ifdef EPROTO
294	EPROTO,
295#else
296	ERRNO_NO_LOCAL_MAPPING,
297#endif
298	"Protocol error" },
299	{ BSM_ELOCKUNMAPPED,
300#ifdef ELOCKUNMAPPED
301	ELOCKUNMAPPED,
302#else
303	ERRNO_NO_LOCAL_MAPPING,
304#endif
305	"Locked lock was unmapped" },
306	{ BSM_ENOTACTIVE,
307#ifdef ENOTACTIVE
308	ENOTACTIVE,
309#else
310	ERRNO_NO_LOCAL_MAPPING,
311#endif
312	"Facility is not active" },
313	{ BSM_EMULTIHOP,
314#ifdef EMULTIHOP
315	EMULTIHOP,
316#else
317	ERRNO_NO_LOCAL_MAPPING,
318#endif
319	"Multihop attempted" },
320	{ BSM_EBADMSG,
321#ifdef EBADMSG
322	EBADMSG,
323#else
324	ERRNO_NO_LOCAL_MAPPING,
325#endif
326	"Bad message" },
327	{ BSM_ENAMETOOLONG, ENAMETOOLONG, "File name too long" },
328	{ BSM_EOVERFLOW, EOVERFLOW, "Value too large to be stored in data type" },
329	{ BSM_ENOTUNIQ,
330#ifdef ENOTUNIQ
331	ENOTUNIQ,
332#else
333	ERRNO_NO_LOCAL_MAPPING,
334#endif
335	"Given log name not unique" },
336	{ BSM_EBADFD,
337#ifdef EBADFD
338	EBADFD,
339#else
340	ERRNO_NO_LOCAL_MAPPING,
341#endif
342	"Given f.d. invalid for this operation" },
343	{ BSM_EREMCHG,
344#ifdef EREMCHG
345	EREMCHG,
346#else
347	ERRNO_NO_LOCAL_MAPPING,
348#endif
349	"Remote address changed" },
350	{ BSM_ELIBACC,
351#ifdef ELIBACC
352	ELIBACC,
353#else
354	ERRNO_NO_LOCAL_MAPPING,
355#endif
356	"Can't access a needed shared lib" },
357	{ BSM_ELIBBAD,
358#ifdef ELIBBAD
359	ELIBBAD,
360#else
361	ERRNO_NO_LOCAL_MAPPING,
362#endif
363	"Accessing a corrupted shared lib" },
364	{ BSM_ELIBSCN,
365#ifdef ELIBSCN
366	ELIBSCN,
367#else
368	ERRNO_NO_LOCAL_MAPPING,
369#endif
370	".lib section in a.out corrupted" },
371	{ BSM_ELIBMAX,
372#ifdef ELIBMAX
373	ELIBMAX,
374#else
375	ERRNO_NO_LOCAL_MAPPING,
376#endif
377	"Attempting to link in too many libs" },
378	{ BSM_ELIBEXEC,
379#ifdef ELIBEXEC
380	ELIBEXEC,
381#else
382	ERRNO_NO_LOCAL_MAPPING,
383#endif
384	"Attempting to exec a shared library" },
385	{ BSM_EILSEQ, EILSEQ, "Illegal byte sequence" },
386	{ BSM_ENOSYS, ENOSYS, "Function not implemented" },
387	{ BSM_ELOOP, ELOOP, "Too many levels of symbolic links" },
388	{ BSM_ERESTART,
389#ifdef ERESTART
390	ERESTART,
391#else
392	ERRNO_NO_LOCAL_MAPPING,
393#endif
394	"Restart syscall" },
395	{ BSM_ESTRPIPE,
396#ifdef ESTRPIPE
397	ESTRPIPE,
398#else
399	ERRNO_NO_LOCAL_MAPPING,
400#endif
401	"If pipe/FIFO, don't sleep in stream head" },
402	{ BSM_ENOTEMPTY, ENOTEMPTY, "Directory not empty" },
403	{ BSM_EUSERS, EUSERS, "Too many users" },
404	{ BSM_ENOTSOCK, ENOTSOCK, "Socket operation on non-socket" },
405	{ BSM_EDESTADDRREQ, EDESTADDRREQ, "Destination address required" },
406	{ BSM_EMSGSIZE, EMSGSIZE, "Message too long" },
407	{ BSM_EPROTOTYPE, EPROTOTYPE, "Protocol wrong type for socket" },
408	{ BSM_ENOPROTOOPT, ENOPROTOOPT, "Protocol not available" },
409	{ BSM_EPROTONOSUPPORT, EPROTONOSUPPORT, "Protocol not supported" },
410	{ BSM_ESOCKTNOSUPPORT, ESOCKTNOSUPPORT, "Socket type not supported" },
411	{ BSM_EOPNOTSUPP, EOPNOTSUPP, "Operation not supported" },
412	{ BSM_EPFNOSUPPORT, EPFNOSUPPORT, "Protocol family not supported" },
413	{ BSM_EAFNOSUPPORT, EAFNOSUPPORT, "Address family not supported by protocol family" },
414	{ BSM_EADDRINUSE, EADDRINUSE, "Address already in use" },
415	{ BSM_EADDRNOTAVAIL, EADDRNOTAVAIL, "Can't assign requested address" },
416	{ BSM_ENETDOWN, ENETDOWN, "Network is down" },
417	{ BSM_ENETRESET, ENETRESET, "Network dropped connection on reset" },
418	{ BSM_ECONNABORTED, ECONNABORTED, "Software caused connection abort" },
419	{ BSM_ECONNRESET, ECONNRESET, "Connection reset by peer" },
420	{ BSM_ENOBUFS, ENOBUFS, "No buffer space available" },
421	{ BSM_EISCONN, EISCONN, "Socket is already connected" },
422	{ BSM_ENOTCONN, ENOTCONN, "Socket is not connected" },
423	{ BSM_ESHUTDOWN, ESHUTDOWN, "Can't send after socket shutdown" },
424	{ BSM_ETOOMANYREFS, ETOOMANYREFS, "Too many references: can't splice" },
425	{ BSM_ETIMEDOUT, ETIMEDOUT, "Operation timed out" },
426	{ BSM_ECONNREFUSED, ECONNREFUSED, "Connection refused" },
427	{ BSM_EHOSTDOWN, EHOSTDOWN, "Host is down" },
428	{ BSM_EHOSTUNREACH, EHOSTUNREACH, "No route to host" },
429	{ BSM_EALREADY, EALREADY, "Operation already in progress" },
430	{ BSM_EINPROGRESS, EINPROGRESS, "Operation now in progress" },
431	{ BSM_ESTALE, ESTALE, "Stale NFS file handle" },
432	{ BSM_EPWROFF,
433#ifdef EPWROFF
434	EPWROFF,
435#else
436	ERRNO_NO_LOCAL_MAPPING,
437#endif
438	"Device power is off" },
439	{ BSM_EDEVERR,
440#ifdef EDEVERR
441	EDEVERR,
442#else
443	ERRNO_NO_LOCAL_MAPPING,
444#endif
445	"Device error" },
446	{ BSM_EBADEXEC,
447#ifdef EBADEXEC
448	EBADEXEC,
449#else
450	ERRNO_NO_LOCAL_MAPPING,
451#endif
452	"Bad executable" },
453	{ BSM_EBADARCH,
454#ifdef EBADARCH
455	EBADARCH,
456#else
457	ERRNO_NO_LOCAL_MAPPING,
458#endif
459	"Bad CPU type in executable" },
460	{ BSM_ESHLIBVERS,
461#ifdef ESHLIBVERS
462	ESHLIBVERS,
463#else
464	ERRNO_NO_LOCAL_MAPPING,
465#endif
466	"Shared library version mismatch" },
467	{ BSM_EBADMACHO,
468#ifdef EBADMACHO
469	EBADMACHO,
470#else
471	ERRNO_NO_LOCAL_MAPPING,
472#endif
473	"Malfored Macho file" },
474	{ BSM_EPOLICY,
475#ifdef EPOLICY
476	EPOLICY,
477#else
478	ERRNO_NO_LOCAL_MAPPING,
479#endif
480	"Operation failed by policy" },
481	{ BSM_EDOTDOT,
482#ifdef EDOTDOT
483	EDOTDOT,
484#else
485	ERRNO_NO_LOCAL_MAPPING,
486#endif
487	"RFS specific error" },
488	{ BSM_EUCLEAN,
489#ifdef EUCLEAN
490	EUCLEAN,
491#else
492	ERRNO_NO_LOCAL_MAPPING,
493#endif
494	"Structure needs cleaning" },
495	{ BSM_ENOTNAM,
496#ifdef ENOTNAM
497	ENOTNAM,
498#else
499	ERRNO_NO_LOCAL_MAPPING,
500#endif
501	"Not a XENIX named type file" },
502	{ BSM_ENAVAIL,
503#ifdef ENAVAIL
504	ENAVAIL,
505#else
506	ERRNO_NO_LOCAL_MAPPING,
507#endif
508	"No XENIX semaphores available" },
509	{ BSM_EISNAM,
510#ifdef EISNAM
511	EISNAM,
512#else
513	ERRNO_NO_LOCAL_MAPPING,
514#endif
515	"Is a named type file" },
516	{ BSM_EREMOTEIO,
517#ifdef EREMOTEIO
518	EREMOTEIO,
519#else
520	ERRNO_NO_LOCAL_MAPPING,
521#endif
522	"Remote I/O error" },
523	{ BSM_ENOMEDIUM,
524#ifdef ENOMEDIUM
525	ENOMEDIUM,
526#else
527	ERRNO_NO_LOCAL_MAPPING,
528#endif
529	"No medium found" },
530	{ BSM_EMEDIUMTYPE,
531#ifdef EMEDIUMTYPE
532	EMEDIUMTYPE,
533#else
534	ERRNO_NO_LOCAL_MAPPING,
535#endif
536	"Wrong medium type" },
537	{ BSM_ENOKEY,
538#ifdef ENOKEY
539	ENOKEY,
540#else
541	ERRNO_NO_LOCAL_MAPPING,
542#endif
543	"Required key not available" },
544	{ BSM_EKEYEXPIRED,
545#ifdef EKEEXPIRED
546	EKEYEXPIRED,
547#else
548	ERRNO_NO_LOCAL_MAPPING,
549#endif
550	"Key has expired" },
551	{ BSM_EKEYREVOKED,
552#ifdef EKEYREVOKED
553	EKEYREVOKED,
554#else
555	ERRNO_NO_LOCAL_MAPPING,
556#endif
557	"Key has been revoked" },
558	{ BSM_EKEYREJECTED,
559#ifdef EKEREJECTED
560	EKEYREJECTED,
561#else
562	ERRNO_NO_LOCAL_MAPPING,
563#endif
564	"Key was rejected by service" },
565};
566static const int bsm_errors_count = sizeof(bsm_errors) / sizeof(bsm_errors[0]);
567
568static const struct bsm_errors *
569au_bsm_error_lookup_errno(int error)
570{
571	int i;
572
573	if (error == ERRNO_NO_LOCAL_MAPPING)
574		return (NULL);
575	for (i = 0; i < bsm_errors_count; i++) {
576		if (bsm_errors[i].be_os_error == error)
577			return (&bsm_errors[i]);
578	}
579	return (NULL);
580}
581
582static const struct bsm_errors *
583au_bsm_error_lookup_bsm(u_char bsm_error)
584{
585	int i;
586
587	for (i = 0; i < bsm_errors_count; i++) {
588		if (bsm_errors[i].be_bsm_error == bsm_error)
589			return (&bsm_errors[i]);
590	}
591	return (NULL);
592}
593
594/*
595 * Converstion from a BSM error to a local error number may fail if either
596 * OpenBSM doesn't recognize the error on the wire, or because there is no
597 * appropriate local mapping.  However, we don't allow conversion to BSM to
598 * fail, we just convert to BSM_UKNOWNERR.
599 */
600int
601au_bsm_to_errno(u_char bsm_error, int *errorp)
602{
603	const struct bsm_errors *bsme;
604
605	bsme = au_bsm_error_lookup_bsm(bsm_error);
606	if (bsme == NULL || bsme->be_os_error == ERRNO_NO_LOCAL_MAPPING)
607		return (-1);
608	*errorp = bsme->be_os_error;
609	return (0);
610}
611
612u_char
613au_errno_to_bsm(int error)
614{
615	const struct bsm_errors *bsme;
616
617	/*
618	 * We should never be passed this libbsm-internal constant, and
619	 * because it is ambiguous we just return an error.
620	 */
621	if (error == ERRNO_NO_LOCAL_MAPPING)
622		return (BSM_UNKNOWNERR);
623	bsme = au_bsm_error_lookup_errno(error);
624	if (bsme == NULL)
625		return (BSM_UNKNOWNERR);
626	return (bsme->be_bsm_error);
627}
628
629#if !defined(KERNEL) && !defined(_KERNEL)
630const char *
631au_strerror(u_char bsm_error)
632{
633	const struct bsm_errors *bsme;
634
635	bsme = au_bsm_error_lookup_bsm(bsm_error);
636	if (bsme == NULL)
637		return ("Unrecognized BSM error");
638	if (bsme->be_os_error != ERRNO_NO_LOCAL_MAPPING)
639		return (strerror(bsme->be_os_error));
640	return (bsme->be_strerror);
641}
642#endif
643