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