1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * Translate Unix errno values to NT status, and NT status to
  29  * DOS-style error class+code (for SMB1)
  30  */
  31 
  32 #include <smbsrv/smb_kproto.h>
  33 #include <smbsrv/smb_kstat.h>
  34 
  35 #include "smbclnt/smb_status2winerr.h"
  36 
  37 
  38 /*
  39  * Map Unix errno values to NT status values.
  40  */
  41 
  42 struct errno2status {
  43         int errnum;
  44         uint_t status;
  45 };
  46 
  47 static const struct errno2status
  48 smb_errno2status_map[] = {
  49         { EPERM,        NT_STATUS_ACCESS_DENIED },
  50         { ENOENT,       NT_STATUS_NO_SUCH_FILE },
  51         /* NB: ESRCH is used to represent stream lookup failures. */
  52         { ESRCH,        NT_STATUS_OBJECT_NAME_NOT_FOUND },
  53         { EINTR,        NT_STATUS_CANCELLED },
  54         { EIO,          NT_STATUS_IO_DEVICE_ERROR },
  55         { ENXIO,        NT_STATUS_BAD_DEVICE_TYPE },
  56         /* E2BIG, ENOEXEC */
  57         { EBADF,        NT_STATUS_INVALID_HANDLE },
  58         /* ECHILD, EAGAIN */
  59         { ENOMEM,       NT_STATUS_NO_MEMORY },
  60         { EACCES,       NT_STATUS_ACCESS_DENIED },
  61         /* EFAULT, ENOTBLK, EBUSY */
  62         { EEXIST,       NT_STATUS_OBJECT_NAME_COLLISION },
  63         { EXDEV,        NT_STATUS_NOT_SAME_DEVICE },
  64         { ENODEV,       NT_STATUS_NO_SUCH_DEVICE },
  65         /* ENOTDIR should be: NT_STATUS_NOT_A_DIRECTORY, but not yet */
  66         { ENOTDIR,      NT_STATUS_OBJECT_PATH_NOT_FOUND },
  67         { EISDIR,       NT_STATUS_FILE_IS_A_DIRECTORY },
  68         { EINVAL,       NT_STATUS_INVALID_PARAMETER },
  69         { ENFILE,       NT_STATUS_TOO_MANY_OPENED_FILES },
  70         { EMFILE,       NT_STATUS_TOO_MANY_OPENED_FILES },
  71         { ENOTTY,       NT_STATUS_INVALID_DEVICE_REQUEST },
  72         /* ENOTTY, ETXTBSY, EFBIG */
  73         { ENOSPC,       NT_STATUS_DISK_FULL },
  74         /* ESPIPE */
  75         { EROFS,        NT_STATUS_ACCESS_DENIED },
  76         { EMLINK,       NT_STATUS_TOO_MANY_LINKS },
  77         { EPIPE,        NT_STATUS_PIPE_BROKEN },
  78         /* EDOM */
  79         /* NB: ERANGE is used to represent lock range I/O conflicts. */
  80         { ERANGE,       NT_STATUS_FILE_LOCK_CONFLICT },
  81         /* ENOMSG, EIDRM, ... */
  82         { ENOTSUP,      NT_STATUS_NOT_SUPPORTED },
  83         { EDQUOT,       NT_STATUS_DISK_FULL },
  84         { EREMOTE,      NT_STATUS_PATH_NOT_COVERED},
  85         { ENAMETOOLONG, NT_STATUS_OBJECT_NAME_INVALID },
  86         { EILSEQ,       NT_STATUS_OBJECT_NAME_INVALID },
  87         { ENOTEMPTY,    NT_STATUS_DIRECTORY_NOT_EMPTY },
  88         { ENOTSOCK,     NT_STATUS_INVALID_HANDLE },
  89         { ESTALE,       NT_STATUS_INVALID_HANDLE },
  90         { 0, 0 }
  91 };
  92 
  93 uint_t
  94 smb_errno2status(int errnum)
  95 {
  96         const struct errno2status *es;
  97 
  98         if (errnum == 0)
  99                 return (0);
 100 
 101         for (es = smb_errno2status_map; es->errnum != 0; es++)
 102                 if (es->errnum == errnum)
 103                         return (es->status);
 104 
 105         return (NT_STATUS_INTERNAL_ERROR);
 106 }
 107 
 108 /*
 109  * Map NT Status codes to Win32 API error numbers.
 110  * But note: we only want the ones below 0xFFFF,
 111  * which can be returned in SMB with class=DOSERR.
 112  */
 113 uint16_t
 114 smb_status2doserr(uint_t status)
 115 {
 116         const struct status2winerr *sw;
 117 
 118         if (status == 0)
 119                 return (0);
 120 
 121         for (sw = smb_status2winerr_map; sw->status != 0; sw++)
 122                 if (sw->status == status && (sw->winerr < 0xFFFF))
 123                         return ((uint16_t)sw->winerr);
 124 
 125         return (ERROR_GEN_FAILURE);
 126 }