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