diff options
Diffstat (limited to 'usr/src/uts')
71 files changed, 2270 insertions, 1852 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c index d29e55eda6..9d6d0c202d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,7 +74,7 @@ smb_com_check_directory(struct smb_request *sr) struct smb_node *dnode; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -88,7 +88,7 @@ smb_com_check_directory(struct smb_request *sr) rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -104,7 +104,7 @@ smb_com_check_directory(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_errno(sr, ENOTDIR); + smbsr_errno(sr, ENOTDIR); /* NOTREACHED */ } @@ -114,8 +114,7 @@ smb_com_check_directory(struct smb_request *sr) SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); if (rc != 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_close.c b/usr/src/uts/common/fs/smbsrv/smb_close.c index c4d129c2e4..f2d7faeb8d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb_close.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,14 +53,13 @@ smb_com_close(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } rc = smb_common_close(sr, last_wtime); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -86,8 +85,7 @@ smb_com_close_and_tree_disconnect(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -96,7 +94,7 @@ smb_com_close_and_tree_disconnect(struct smb_request *sr) smb_tree_disconnect(sr->tid_tree); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c index d3a462fbc5..5e0d94976b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,22 +37,10 @@ #include <smbsrv/ntstatus.h> #include <smbsrv/smbinfo.h> #include <sys/fcntl.h> +#include <sys/nbmlock.h> extern uint32_t smb_is_executable(char *path); -#define DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0) - -#define DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0) - -#define DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0) - -#define DENY_RW(share_access) \ - ((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0) - -#define DENY_ALL(share_access) (share_access == 0) - -#define DENY_NONE(share_access) (share_access == FILE_SHARE_ALL) - /* * The default stability mode is to perform the write-through * behaviour requested by the client. @@ -219,130 +207,6 @@ smb_ofun_to_crdisposition(uint16_t ofun) } /* - * smb_open_share_check - * - * check file sharing rules for current open request - * against the given existing open. - * - * Returns NT_STATUS_SHARING_VIOLATION if there is any - * sharing conflict, otherwise returns NT_STATUS_SUCCESS. - */ -uint32_t -smb_open_share_check(struct smb_request *sr, - struct smb_node *node, - struct smb_ofile *open) -{ - uint32_t desired_access; - uint32_t share_access; - - desired_access = sr->arg.open.desired_access; - share_access = sr->arg.open.share_access; - - /* - * As far as I can tell share modes are not relevant to - * directories. The check for exclusive access (Deny RW) - * remains because I don't know whether or not it was here - * for a reason. - */ - if (node->attr.sa_vattr.va_type == VDIR) { - if (DENY_RW(open->f_share_access) && - (node->n_orig_uid != crgetuid(sr->user_cr))) { - return (NT_STATUS_SHARING_VIOLATION); - } - - return (NT_STATUS_SUCCESS); - } - - /* if it's just meta data */ - if ((open->f_granted_access & FILE_DATA_ALL) == 0) - return (NT_STATUS_SUCCESS); - - /* - * Check requested share access against the - * open granted (desired) access - */ - if (DENY_DELETE(share_access) && (open->f_granted_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_READ(share_access) && - (open->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_WRITE(share_access) && - (open->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - /* check requested desired access against the open share access */ - if (DENY_DELETE(open->f_share_access) && (desired_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_READ(open->f_share_access) && - (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_WRITE(open->f_share_access) && - (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_file_share_check - * - * check file sharing rules for current open request - * against all existing opens for a file. - * - * Returns NT_STATUS_SHARING_VIOLATION if there is any - * sharing conflict, otherwise returns NT_STATUS_SUCCESS. - */ -uint32_t -smb_file_share_check(struct smb_request *sr, struct smb_node *node) -{ - struct smb_ofile *open; - uint32_t status; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - /* if it's just meta data */ - if ((sr->arg.open.desired_access & FILE_DATA_ALL) == 0) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - open = smb_llist_head(&node->n_ofile_list); - while (open) { - status = smb_open_share_check(sr, node, open); - if (status == NT_STATUS_SHARING_VIOLATION) { - smb_llist_exit(&node->n_ofile_list); - return (status); - } - open = smb_llist_next(&node->n_ofile_list, open); - } - smb_llist_exit(&node->n_ofile_list); - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_amask_to_amode - * Converts specific read/write access rights of access mask to access - * mode flags. - */ -int -smb_amask_to_amode(unsigned long amask) -{ - if ((amask & FILE_READ_DATA) && - (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (O_RDWR); - - if (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) - return (O_WRONLY); - - return (O_RDONLY); -} - -/* * smb_open_subr * * Notes on write-through behaviour. It looks like pre-LM0.12 versions @@ -364,6 +228,7 @@ smb_amask_to_amode(unsigned long amask) * in which case it won't return to the caller. Be careful how you * handle things in here. */ + uint32_t smb_open_subr(struct smb_request *sr) { @@ -385,6 +250,8 @@ smb_open_subr(struct smb_request *sr) int is_stream; int lookup_flags = SMB_FOLLOW_LINKS; uint32_t daccess; + uint32_t share_access = op->share_access; + uint32_t uniq_fid; is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0; @@ -397,7 +264,7 @@ smb_open_subr(struct smb_request *sr) if ((op->create_disposition != FILE_CREATE) && (op->create_disposition != FILE_OPEN_IF) && (op->create_disposition != FILE_OPEN)) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_ACCESS); /* invalid open mode */ /* NOTREACHED */ @@ -417,7 +284,7 @@ smb_open_subr(struct smb_request *sr) sr->uid_user->u_name, xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES)); - smbsr_raise_cifs_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, + smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, ERRDOS, ERROR_TOO_MANY_OPEN_FILES); /* NOTREACHED */ } @@ -437,7 +304,7 @@ smb_open_subr(struct smb_request *sr) * raise an exception or return success here. */ if ((rc = smb_rpc_open(sr)) != 0) { - smbsr_raise_nt_error(sr, rc); + smbsr_error(sr, rc, 0, 0); /* NOTREACHED */ } else { return (NT_STATUS_SUCCESS); @@ -445,13 +312,13 @@ smb_open_subr(struct smb_request *sr) break; default: - smbsr_raise_error(sr, ERRSRV, ERRinvdevice); + smbsr_error(sr, 0, ERRSRV, ERRinvdevice); /* NOTREACHED */ break; } if ((pathlen = strlen(op->fqi.path)) >= MAXPATHLEN) { - smbsr_raise_error(sr, ERRSRV, ERRfilespecs); + smbsr_error(sr, 0, ERRSRV, ERRfilespecs); /* NOTREACHED */ } @@ -466,7 +333,7 @@ smb_open_subr(struct smb_request *sr) op->fqi.srch_attr = op->fqi.srch_attr; if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) { - smbsr_raise_cifs_error(sr, status, ERRDOS, ERROR_INVALID_NAME); + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } @@ -476,7 +343,7 @@ smb_open_subr(struct smb_request *sr) if (rc = smb_pathname_reduce(sr, sr->user_cr, op->fqi.path, sr->tid_tree->t_snode, cur_node, &op->fqi.dir_snode, op->fqi.last_comp)) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -508,26 +375,41 @@ smb_open_subr(struct smb_request *sr) } else { smb_node_release(op->fqi.dir_snode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + /* + * The uniq_fid is a CIFS-server-wide unique identifier for an ofile + * which is used to uniquely identify open instances for the + * VFS share reservation mechanism (accessed via smb_fsop_shrlock()). + */ + + uniq_fid = SMB_UNIQ_FID(); + if (op->fqi.last_comp_was_found) { node = op->fqi.last_snode; dnode = op->fqi.dir_snode; /* + * Enter critical region for share reservations. + * (See comments above smb_fsop_shrlock().) + */ + + rw_enter(&node->n_share_lock, RW_WRITER); + + /* * Reject this request if the target is a directory * and the client has specified that it must not be * a directory (required by Lotus Notes). */ if ((op->create_options & FILE_NON_DIRECTORY_FILE) && (op->fqi.last_attr.sa_vattr.va_type == VDIR)) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_FILE_IS_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -539,19 +421,20 @@ smb_open_subr(struct smb_request *sr) * Directories cannot be opened * with the above commands */ + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_FILE_IS_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } } else if (op->my_flags & MYF_MUST_BE_DIRECTORY) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_NOT_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, ERRDOS, ERROR_DIRECTORY); /* NOTREACHED */ } @@ -561,10 +444,11 @@ smb_open_subr(struct smb_request *sr) * flag is set. */ if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_DELETE_PENDING, + smbsr_error(sr, NT_STATUS_DELETE_PENDING, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -573,12 +457,12 @@ smb_open_subr(struct smb_request *sr) * Specified file already exists so the operation should fail. */ if (op->create_disposition == FILE_CREATE) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, - ERROR_ALREADY_EXISTS); + smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERROR_ALREADY_EXISTS); /* NOTREACHED */ } @@ -591,18 +475,42 @@ smb_open_subr(struct smb_request *sr) if (node->attr.sa_vattr.va_type != VDIR) { if (op->desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_error(sr, ERRDOS, - ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); /* NOTREACHED */ } } } - status = smb_file_share_check(sr, node); + /* + * The following check removes the need to check share + * reservations again when a truncate is done. + */ + + if ((op->create_disposition == FILE_SUPERSEDE) || + (op->create_disposition == FILE_OVERWRITE_IF) || + (op->create_disposition == FILE_OVERWRITE)) { + + if (!(op->desired_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA))) { + rw_exit(&node->n_share_lock); + smb_node_release(node); + smb_node_release(dnode); + SMB_NULL_FQI_NODES(op->fqi); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); + } + } + + status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, + op->desired_access, share_access); + if (status == NT_STATUS_SHARING_VIOLATION) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); @@ -613,19 +521,19 @@ smb_open_subr(struct smb_request *sr) op->desired_access); if (status != NT_STATUS_SUCCESS) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); + if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { - smbsr_raise_cifs_error(sr, - status, - ERRDOS, - ERROR_PRIVILEGE_NOT_HELD); + smbsr_error(sr, status, + ERRDOS, ERROR_PRIVILEGE_NOT_HELD); } else { - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, - ERRDOS, - ERROR_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); } } @@ -634,14 +542,16 @@ smb_open_subr(struct smb_request *sr) * has the file open, this will force a flush or close, * which may affect the outcome of any share checking. */ + if (OPLOCKS_IN_FORCE(node)) { status = smb_break_oplock(sr, node); if (status != NT_STATUS_SUCCESS) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, status, + smbsr_error(sr, status, ERRDOS, ERROR_VC_DISCONNECTED); /* NOTREACHED */ } @@ -652,29 +562,37 @@ smb_open_subr(struct smb_request *sr) case FILE_OVERWRITE_IF: case FILE_OVERWRITE: if (node->attr.sa_vattr.va_type == VDIR) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, ERRDOS, - ERROR_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } if (node->attr.sa_vattr.va_size != op->dsize) { node->flags &= ~NODE_FLAGS_SET_SIZE; + bzero(&new_attr, sizeof (new_attr)); new_attr.sa_vattr.va_size = op->dsize; new_attr.sa_mask = SMB_AT_SIZE; - if ((rc = smb_fsop_setattr(sr, sr->user_cr, - (&op->fqi)->last_snode, &new_attr, - &op->fqi.last_attr)) != 0) { + + rc = smb_fsop_setattr(sr, sr->user_cr, + node, &new_attr, &op->fqi.last_attr); + + if (rc) { + smb_fsop_unshrlock(sr->user_cr, + node, uniq_fid); + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + op->dsize = op->fqi.last_attr.sa_vattr.va_size; } /* @@ -712,11 +630,10 @@ smb_open_subr(struct smb_request *sr) * fail with these two dispositions */ if (is_stream) - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_NOT_FOUND, + smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERROR_FILE_NOT_FOUND); else - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOTREACHED */ } @@ -731,32 +648,93 @@ smb_open_subr(struct smb_request *sr) new_attr.sa_vattr.va_type = VREG; new_attr.sa_vattr.va_mode = 0666; new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; + + /* + * A problem with setting the readonly bit at + * create time is that this bit will prevent + * writes to the file from the same fid (which + * should be allowed). + * + * The solution is to set the bit at close time. + * Meanwhile, to prevent racing opens from being + * able to write to the file, the bit is set at + * create time until share reservations can be set + * to prevent write and delete access. At that point, + * the bit can be turned off until close (so as to + * allow writes from the same fid to the file). + */ + + if (op->dattr & SMB_FA_READONLY) { + new_attr.sa_dosattr = FILE_ATTRIBUTE_READONLY; + new_attr.sa_mask |= SMB_AT_DOSATTR; + } + rc = smb_fsop_create(sr, sr->user_cr, dnode, op->fqi.last_comp, &new_attr, &op->fqi.last_snode, &op->fqi.last_attr); + if (rc != 0) { smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + if (op->dattr & SMB_FA_READONLY) { + share_access &= ~(FILE_SHARE_WRITE | + FILE_SHARE_DELETE); + } + + node = op->fqi.last_snode; + + rw_enter(&node->n_share_lock, RW_WRITER); + + status = smb_fsop_shrlock(sr->user_cr, node, + uniq_fid, op->desired_access, + share_access); + + if (status == NT_STATUS_SHARING_VIOLATION) { + rw_exit(&node->n_share_lock); + smb_node_release(node); + smb_node_release(dnode); + SMB_NULL_FQI_NODES(op->fqi); + return (status); + } + + new_attr = op->fqi.last_attr; + new_attr.sa_mask = 0; + + if (op->dattr & SMB_FA_READONLY) { + new_attr.sa_dosattr &= ~FILE_ATTRIBUTE_READONLY; + new_attr.sa_mask |= SMB_AT_DOSATTR; + } + if (op->dsize) { new_attr.sa_vattr.va_size = op->dsize; - new_attr.sa_mask = SMB_AT_SIZE; - rc = smb_fsop_setattr(sr, sr->user_cr, - op->fqi.last_snode, &new_attr, - &op->fqi.last_attr); + new_attr.sa_mask |= SMB_AT_SIZE; + } + + if (new_attr.sa_mask) { + node->attr = new_attr; + node->what = new_attr.sa_mask; + rc = smb_sync_fsattr(sr, sr->user_cr, node); + if (rc != 0) { - smb_node_release(op->fqi.last_snode); + smb_fsop_unshrlock(sr->user_cr, node, + uniq_fid); + + rw_exit(&node->n_share_lock); + smb_node_release(node); (void) smb_fsop_remove(sr, sr->user_cr, dnode, op->fqi.last_comp, 0); smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ + } else { + op->fqi.last_attr = node->attr; } } @@ -772,30 +750,33 @@ smb_open_subr(struct smb_request *sr) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + + node = op->fqi.last_snode; + rw_enter(&node->n_share_lock, RW_WRITER); } created = 1; op->action_taken = SMB_OACT_CREATED; } - if (node == 0) { - node = op->fqi.last_snode; - } - if ((op->fqi.last_attr.sa_vattr.va_type != VREG) && (op->fqi.last_attr.sa_vattr.va_type != VDIR) && (op->fqi.last_attr.sa_vattr.va_type != VLNK)) { /* not allowed to do this */ + + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + SMB_DEL_NEWOBJ(op->fqi); + rw_exit(&node->n_share_lock); smb_node_release(node); if (created) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -811,17 +792,20 @@ smb_open_subr(struct smb_request *sr) */ of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access, - op->create_options, op->share_access, SMB_FTYPE_DISK, NULL, 0, - &err); + op->create_options, share_access, SMB_FTYPE_DISK, NULL, 0, + uniq_fid, &err); if (of == NULL) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + SMB_DEL_NEWOBJ(op->fqi); + rw_exit(&node->n_share_lock); smb_node_release(node); if (created) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, err.status, err.errcls, err.errcode); + smbsr_error(sr, err.status, err.errcls, err.errcode); /* NOTREACHED */ } @@ -847,14 +831,20 @@ smb_open_subr(struct smb_request *sr) op->my_flags &= ~MYF_OPLOCK_MASK; if (status != NT_STATUS_SUCCESS) { + rw_exit(&node->n_share_lock); + /* + * smb_fsop_unshrlock() and smb_fsop_close() + * are called from smb_ofile_close() + */ (void) smb_ofile_close(of, 0); smb_ofile_release(of); if (created) smb_rwx_rwexit(&dnode->n_lock); + smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, status, + smbsr_error(sr, status, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ } @@ -868,11 +858,15 @@ smb_open_subr(struct smb_request *sr) /* * Clients may set the DOS readonly bit on create but they * expect subsequent write operations on the open fid to - * succeed. Thus the DOS readonly bit is not set until the - * file is closed. The NODE_CREATED_READONLY flag will - * inhibit other attempts to open the file with write access - * and act as the indicator to set the DOS readonly bit on + * succeed. Thus the DOS readonly bit is not set permanently + * until the file is closed. The NODE_CREATED_READONLY flag + * will act as the indicator to set the DOS readonly bit on * close. + * Above, the readonly bit is set on create, share + * reservations are set, and then the bit is unset. + * These actions allow writes to the open fid to succeed + * until the file is closed while preventing write access + * from other opens while this fid is active. */ if (op->dattr & SMB_FA_READONLY) { node->flags |= NODE_CREATED_READONLY; @@ -913,9 +907,11 @@ smb_open_subr(struct smb_request *sr) sr->smb_fid = of->f_fid; sr->fid_ofile = of; - if (created) { + rw_exit(&node->n_share_lock); + + if (created) smb_rwx_rwexit(&dnode->n_lock); - } + smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_search.c b/usr/src/uts/common/fs/smbsrv/smb_common_search.c index a17555669b..84d35fe9b0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_search.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,6 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) smb_odir_t *od; smb_node_t *node; char *last_component; - smb_session_t *session = sr->session; unsigned int rc; int erc; @@ -51,14 +50,14 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &node, last_component)) != 0) { kmem_free(last_component, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if ((node->vp)->v_type != VDIR) { smb_node_release(node); kmem_free(last_component, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRbadpath); + smbsr_error(sr, 0, ERRDOS, ERRbadpath); /* NOTREACHED */ } @@ -67,18 +66,11 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) smb_node_release(node); kmem_free(last_component, MAXNAMELEN); if (sr->smb_com == SMB_COM_SEARCH) { - if (session->capabilities & CAP_STATUS32) { - smbsr_setup_nt_status(sr, - ERROR_SEVERITY_WARNING, - NT_STATUS_NO_MORE_FILES); - return (SDRC_NORMAL_REPLY); - } else { - smbsr_raise_error(sr, - ERRDOS, ERROR_NO_MORE_FILES); - /* NOTREACHED */ - } + smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, + ERRDOS, ERROR_NO_MORE_FILES); + return (SDRC_NORMAL_REPLY); } else { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -89,7 +81,7 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) kmem_free(last_component, sizeof (od->d_pattern)); if (od == NULL) { smb_node_release(node); - smbsr_raise_error(sr, ERRDOS, ERROR_NO_MORE_FILES); + smbsr_error(sr, 0, ERRDOS, ERROR_NO_MORE_FILES); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c index 2558716c5e..dff0a689dd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ @@ -89,7 +89,7 @@ smb_com_transaction(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == NULL) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -114,17 +114,17 @@ smb_com_transaction(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, suwcnt * 2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -132,7 +132,7 @@ smb_com_transaction(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -144,7 +144,7 @@ smb_com_transaction(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -161,13 +161,13 @@ smb_com_transaction_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -194,13 +194,13 @@ smb_com_transaction_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -266,7 +266,7 @@ smb_com_transaction2(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == 0) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -278,17 +278,17 @@ smb_com_transaction2(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, suwcnt*2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -296,7 +296,7 @@ smb_com_transaction2(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -308,7 +308,7 @@ smb_com_transaction2(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -325,13 +325,13 @@ smb_com_transaction2_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -359,13 +359,13 @@ smb_com_transaction2_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -418,15 +418,15 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case NT_TRANSACT_QUERY_QUOTA: (void) smb_nt_transact_query_quota(sr, xa); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ case NT_TRANSACT_SET_QUOTA: - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ default: - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ } @@ -441,7 +441,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case SDRC_UNIMPLEMENTED: case SDRC_UNSUPPORTED: - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ default: @@ -455,7 +455,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) if (xa->smb_msrcnt < n_setup || xa->smb_mprcnt < n_param || xa->smb_mdrcnt < n_data) { - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ } @@ -539,7 +539,7 @@ smb_com_nt_transact(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); if (xa == 0) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -552,17 +552,17 @@ smb_com_nt_transact(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, SetupCount * 2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -570,7 +570,7 @@ smb_com_nt_transact(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -582,7 +582,7 @@ smb_com_nt_transact(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -599,13 +599,13 @@ smb_com_nt_transact_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -633,13 +633,13 @@ smb_com_nt_transact_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -1926,8 +1926,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -1942,7 +1941,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case TRANS_WAIT_NMPIPE: if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOT REACHED */ } rc = SDRC_NORMAL_REPLY; @@ -2120,8 +2119,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2134,8 +2132,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2148,8 +2145,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2162,8 +2158,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2176,8 +2171,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c index 7906233a35..6947474f77 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,7 @@ smbsr_connect_tree(struct smb_request *sr) char *sharename; char *access_msg; int32_t stype; + DWORD status; int rc; errmsg[0] = '\0'; @@ -77,12 +78,12 @@ smbsr_connect_tree(struct smb_request *sr) * Looks like a UNC path, make sure the format is correct. */ if (sharename[1] != '\\') { - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } if ((sharename = strchr(sharename+2, '\\')) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } @@ -91,12 +92,12 @@ smbsr_connect_tree(struct smb_request *sr) /* * This should be a sharename: no embedded '\' allowed. */ - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } if (smb_get_stype(sharename, sr->arg.tcon.service, &stype) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_BAD_DEVICE_TYPE, + smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, ERRDOS, ERROR_BAD_DEV_TYPE); /* NOTREACHED */ } @@ -106,14 +107,11 @@ smbsr_connect_tree(struct smb_request *sr) smbsr_share_report(sr, sharename, access_msg, errmsg); /* - * W2K sometimes tries to connect to user shares using an - * anonymous IPC connection. NT returns access denied. + * Windows 2000 may try to connect to user shares using + * an anonymous IPC connection. NT returns access denied. */ - if (rc == ERRaccess) - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, - ERRSRV, ERRaccess); - else - smbsr_raise_error(sr, ERRSRV, rc); + status = (rc == ERRaccess) ? NT_STATUS_ACCESS_DENIED : 0; + smbsr_error(sr, status, ERRSRV, rc); /* NOTREACHED */ } @@ -167,11 +165,11 @@ smbsr_share_report(struct smb_request *sr, char *sharename, /* * smbsr_setup_share * - * This is where the real of setting up share is done. The main thing - * to note is that we resolve ambiguities by assuming that a directory is - * being requested. This function returns error codes, rather than calling - * smbsr_raise_error. We return 0 on success or a non-zero error code if - * there is a problem. + * This is where the real of setting up share is done. + * Note that ambiguities are resolved by assuming that a directory + * is being requested. + * + * Returns 0 on success or a non-zero error code on failure. */ int smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype, diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c index 8fd289bb75..c38bbfd819 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,13 +62,13 @@ smb_com_create(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -107,13 +107,13 @@ smb_com_create_new(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -165,13 +165,13 @@ smb_com_create_temporary(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -198,7 +198,7 @@ smb_common_create(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c index e369f59b47..cb6e3f6e72 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,11 +93,7 @@ smb_com_create_directory(struct smb_request *sr) } if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_NAME); - + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } @@ -110,12 +106,12 @@ smb_com_create_directory(struct smb_request *sr) while (smbpath_next(spp)) { rc = smb_common_create_directory(sr); if (rc != 0 && rc != EEXIST) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); } /* We should have created one directory successfully! */ if (rc != 0) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); smbsr_encode_empty_result(sr); return (SDRC_NORMAL_REPLY); @@ -164,7 +160,7 @@ smb_common_create_directory(struct smb_request *sr) struct smb_node *node; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c index f35e3c4273..c3a4dad862 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,10 +28,10 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smbinfo.h> +#include <sys/nbmlock.h> -static DWORD smb_delete_check(struct smb_request *sr, struct smb_node *node, - uint16_t dattr, smb_error_t *smberr); -static DWORD smb_delete_share_check(struct smb_node *node); +static uint32_t smb_delete_check(smb_request_t *sr, smb_node_t *node, + smb_error_t *smberr); /* * smb_com_delete @@ -104,32 +104,22 @@ smb_com_delete(struct smb_request *sr) int is_stream; smb_odir_context_t *pc; - pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); - fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); - sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); - name = kmem_alloc(MAXNAMELEN, KM_SLEEP); - fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); - if (smbsr_decode_vwv(sr, "w", &sattr) != 0) { - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); smbsr_decode_error(sr); /* NOTREACHED */ } if (smbsr_decode_data(sr, "%S", sr, &path) != 0) { - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); smbsr_decode_error(sr); /* NOTREACHED */ } + pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); + fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); + sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); + name = kmem_alloc(MAXNAMELEN, KM_SLEEP); + fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); + is_stream = smb_stream_parse_name(path, fname, sname); (void) smb_rdir_open(sr, path, sattr); @@ -145,14 +135,50 @@ smb_com_delete(struct smb_request *sr) while ((rc = smb_rdir_next(sr, &node, pc)) == 0) { (void) strlcpy(name, pc->dc_name, MAXNAMELEN); - if (smb_delete_check(sr, node, pc->dc_dattr, &smberr) - != NT_STATUS_SUCCESS) { + if (pc->dc_dattr & SMB_FA_DIRECTORY) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_ACCESS_DENIED; + smberr.status = NT_STATUS_FILE_IS_A_DIRECTORY; smb_node_release(node); goto delete_error; } - smb_node_release(node); - node = NULL; + if ((pc->dc_dattr & SMB_FA_READONLY) || + (node->flags & NODE_CREATED_READONLY)) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_ACCESS_DENIED; + smberr.status = NT_STATUS_CANNOT_DELETE; + smb_node_release(node); + goto delete_error; + } + + /* + * NT does not always close a file immediately, which + * can cause the share and access checking to fail + * (the node refcnt is greater than one), and the file + * doesn't get deleted. Breaking the oplock before + * share and access checking gives the client a chance + * to close the file. + */ + + if (OPLOCKS_IN_FORCE(node)) { + smberr.status = smb_break_oplock(sr, node); + + if (smberr.status != NT_STATUS_SUCCESS) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_VC_DISCONNECTED; + smb_node_release(node); + goto delete_error; + } + } + + smb_node_start_crit(node, RW_READER); + + if (smb_delete_check(sr, node, &smberr)) { + smb_node_end_crit(node); + smb_node_release(node); + goto delete_error; + } if (is_stream) { /* @@ -177,6 +203,10 @@ smb_com_delete(struct smb_request *sr) name, od); } + smb_node_end_crit(node); + smb_node_release(node); + node = NULL; + if (rc != 0) { if (rc != ENOENT) { smb_rdir_close(sr); @@ -185,7 +215,7 @@ smb_com_delete(struct smb_request *sr) kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } } else { @@ -201,7 +231,7 @@ smb_com_delete(struct smb_request *sr) kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -231,57 +261,20 @@ delete_error: kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_cifs_error(sr, - smberr.status, smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ return (SDRC_NORMAL_REPLY); /* compiler complains otherwise */ } -static DWORD -smb_delete_check( - struct smb_request *sr, - struct smb_node *node, - uint16_t dattr, - smb_error_t *smberr) +uint32_t +smb_delete_check(smb_request_t *sr, smb_node_t *node, smb_error_t *smberr) { - if (dattr & SMB_FA_DIRECTORY) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_ACCESS_DENIED; - smberr->status = NT_STATUS_FILE_IS_A_DIRECTORY; - return (NT_STATUS_UNSUCCESSFUL); - } - - if ((dattr & SMB_FA_READONLY) || - (node->flags & NODE_CREATED_READONLY)) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_ACCESS_DENIED; - smberr->status = NT_STATUS_CANNOT_DELETE; - return (NT_STATUS_UNSUCCESSFUL); - } - - /* - * NT does not always close a file immediately, which - * can cause the share and access checking to fail - * (the node refcnt is greater than one), and the file - * doesn't get deleted. Breaking the oplock before - * share and access checking gives the client a chance - * to close the file. - */ - if (OPLOCKS_IN_FORCE(node)) { - smberr->status = smb_break_oplock(sr, node); + smberr->status = smb_node_delete_check(node); - if (smberr->status != NT_STATUS_SUCCESS) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_VC_DISCONNECTED; - return (NT_STATUS_UNSUCCESSFUL); - } - } - - smberr->status = smb_delete_share_check(node); if (smberr->status == NT_STATUS_SHARING_VIOLATION) { smberr->errcls = ERRDOS; smberr->errcode = ERROR_SHARING_VIOLATION; - return (NT_STATUS_UNSUCCESSFUL); + return (smberr->status); } /* @@ -294,61 +287,15 @@ smb_delete_check( * W2K rejects lock requests on open files which are opened * with Metadata open modes. The error is STATUS_ACCESS_DENIED. */ - if (smb_lock_range_access(sr, node, 0, 0, FILE_WRITE_DATA) != - NT_STATUS_SUCCESS) { + + smberr->status = smb_range_check(sr, sr->user_cr, node, 0, + UINT64_MAX, B_TRUE); + + if (smberr->status != NT_STATUS_SUCCESS) { smberr->errcls = ERRDOS; smberr->errcode = ERROR_ACCESS_DENIED; smberr->status = NT_STATUS_ACCESS_DENIED; - return (NT_STATUS_UNSUCCESSFUL); } - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_delete_share_check - * - * An open file can be deleted only if opened for - * accessing meta data. Share modes aren't important - * in this case. - * - * NOTE: there is another mechanism for deleting an - * open file that NT clients usually use this method. - * That's setting "Delete on close" flag for an open - * file, in this way the file will be deleted after - * last close. This flag can be set by SmbTrans2SetFileInfo - * with FILE_DISPOSITION_INFO information level. - * For setting this flag file should be opened by - * DELETE access in the FID that is passed in the Trans2 - * request. - */ -static DWORD -smb_delete_share_check(struct smb_node *node) -{ - smb_ofile_t *file; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - if (node->attr.sa_vattr.va_type == VDIR) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - file = smb_llist_head(&node->n_ofile_list); - while (file) { - ASSERT(file->f_magic == SMB_OFILE_MAGIC); - if (file->f_granted_access & - (FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_APPEND_DATA | - FILE_EXECUTE | - DELETE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - file = smb_llist_next(&node->n_ofile_list, file); - } - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SUCCESS); + return (smberr->status); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c index e959b240b8..514551ad97 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -63,7 +63,7 @@ smb_com_delete_directory(struct smb_request *sr) int rc; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -77,7 +77,7 @@ smb_com_delete_directory(struct smb_request *sr) rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -88,7 +88,7 @@ smb_com_delete_directory(struct smb_request *sr) smb_node_release(sr->arg.dirop.fqi.dir_snode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_CANNOT_DELETE, + smbsr_error(sr, NT_STATUS_CANNOT_DELETE, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -102,7 +102,7 @@ smb_com_delete_directory(struct smb_request *sr) if (rc != 0) { smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c index 96a23bb995..0cc54ae43e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * @@ -145,7 +145,6 @@ #define SMB_ALL_DISPATCH_STAT_INCR(stat) atomic_inc_64(&stat); -int smb_dispatch_diags = 0; static kstat_t *smb_dispatch_ksp = NULL; static kstat_named_t *smb_dispatch_kstat_data = NULL; static int smb_dispatch_kstat_size = 0; @@ -773,6 +772,7 @@ smb_dispatch_request(struct smb_request *sr) { int rc; smb_dispatch_table_t *sdd; + smb_error_t err; ASSERT(sr->tid_tree == 0); ASSERT(sr->uid_user == 0); @@ -834,20 +834,16 @@ smb_dispatch_request(struct smb_request *sr) sr->first_smb_com = sr->smb_com; /* - * Verify SMB signature if signing is enabled, - * dialiect is NT LM 0.12, + * Verify SMB signature if signing is enabled, dialect is NT LM 0.12, * signing was negotiated and authentication has occurred. */ if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_request(sr) != 0) { - /* Reply with ACCESS_DENIED */ - if (sr->session->capabilities & CAP_STATUS32) - smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, - NT_STATUS_ACCESS_DENIED); - else { - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRnoaccess; - } + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_ACCESS_DENIED; + err.errcls = ERRDOS; + err.errcode = ERROR_ACCESS_DENIED; + smbsr_set_error(sr, &err); rc = -1; smb_rwx_rwenter(&sr->session->s_lock, RW_READER); goto reply_error; @@ -956,15 +952,14 @@ andx_more: sr->uid_user = smb_user_lookup_by_uid(sr->session, &sr->user_cr, sr->smb_uid); if (sr->uid_user == NULL) { - smbsr_raise_error(sr, ERRSRV, ERRbaduid); + smbsr_error(sr, 0, ERRSRV, ERRbaduid); /* NOTREACHED */ } if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) { sr->tid_tree = smb_tree_lookup_by_tid( sr->uid_user, sr->smb_tid); if (sr->tid_tree == NULL) { - smbsr_raise_error(sr, ERRSRV, - ERRinvnid); + smbsr_error(sr, 0, ERRSRV, ERRinvnid); /* NOTREACHED */ } } @@ -1274,78 +1269,15 @@ smbsr_encode_empty_result(struct smb_request *sr) } /* - * cifs_raise_error - * - * Temporary workaround to the NT status versus Win32/SMB error codes - * decision: just report them both here. - */ -void -smbsr_raise_cifs_error(struct smb_request *sr, - DWORD status, - int error_class, - int error_code) -{ - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, error_class, error_code); - - /* NOTREACHED */ -} - -void -smbsr_raise_error(struct smb_request *sr, int errcls, int errcod) -{ - sr->smb_rcls = (unsigned char)errcls; - sr->smb_err = (uint16_t)errcod; - longjmp(&sr->exjb); -} - -/* - * smbsr_setup_nt_status - * - * Set up an NT status in the smb_request but don't long jump or try - * to do any error handling. There are times when we need a status set - * up in the response to indicate that the request has either failed - * or, at least, is only partially complete (possibly indicated by the - * severity) but we also need to return some information to the client. - */ -void -smbsr_setup_nt_status(struct smb_request *sr, - uint32_t severity, - uint32_t nt_status) -{ - nt_status |= severity; - sr->smb_rcls = nt_status & 0xff; - sr->smb_reh = (nt_status >> 8) & 0xff; - sr->smb_err = nt_status >> 16; - sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; -} - -void -smbsr_raise_nt_error(struct smb_request *sr, uint32_t errcod) -{ - errcod |= 0xc0000000; - sr->smb_rcls = errcod & 0xff; - sr->smb_reh = (errcod >> 8) & 0xff; - sr->smb_err = errcod >> 16; - sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; - longjmp(&sr->exjb); -} - - -/* - * Attempt to map errno values to SMB and NT status values. - * Note: ESRCH is used as special case to handle a lookup - * failure on streams. + * Map errno values to SMB and NT status values. + * Note: ESRCH is a special case to handle a streams lookup failure. */ static struct { - int unix_errno; - int smb_error_class; - int smb_error_value; - DWORD nt_status; -} -smb_errno_map[] = { + int errnum; + int errcls; + int errcode; + DWORD status32; +} smb_errno_map[] = { { ENOSPC, ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL }, { EDQUOT, ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL }, { EPERM, ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED }, @@ -1375,74 +1307,115 @@ smb_errno_map[] = { }; void -smb_errmap_unix2smb(int en, smb_error_t *smberr) +smbsr_map_errno(int errnum, smb_error_t *err) { int i; - smberr->status = NT_STATUS_UNSUCCESSFUL; - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_GEN_FAILURE; - for (i = 0; i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); ++i) { - if (smb_errno_map[i].unix_errno == en) { - smberr->status = smb_errno_map[i].nt_status; - smberr->errcls = smb_errno_map[i].smb_error_class; - smberr->errcode = smb_errno_map[i].smb_error_value; + if (smb_errno_map[i].errnum == errnum) { + err->severity = ERROR_SEVERITY_ERROR; + err->status = smb_errno_map[i].status32; + err->errcls = smb_errno_map[i].errcls; + err->errcode = smb_errno_map[i].errcode; return; } } + + err->severity = ERROR_SEVERITY_ERROR; + err->status = NT_STATUS_INTERNAL_ERROR; + err->errcls = ERRDOS; + err->errcode = ERROR_INTERNAL_ERROR; } -int -smbsr_set_errno(struct smb_request *sr, int en) +void +smbsr_errno(struct smb_request *sr, int errnum) { - int i; + smb_error_t err; - ASSERT(en != -1); + smbsr_map_errno(errnum, &err); + smbsr_set_error(sr, &err); + longjmp(&sr->exjb); + /* NOTREACHED */ +} - /* - * If the client supports 32-bit NT status values, check for - * an appropriate mapping and raise an NT error, control won't - * return here due to the longjmp in smbsr_raise_nt_error. - */ - if (sr->session->capabilities & CAP_STATUS32) { - for (i = 0; - i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); - ++i) { - if (smb_errno_map[i].unix_errno == en) { - smbsr_raise_nt_error(sr, - smb_errno_map[i].nt_status); - /* NOTREACHED */ - } - } - } else { - for (i = 0; - i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); - ++i) { - if (smb_errno_map[i].unix_errno == en) { - sr->smb_rcls = smb_errno_map[i].smb_error_class; - sr->smb_err = smb_errno_map[i].smb_error_value; - return (0); - } - } - } +/* + * Report a request processing warning. + */ +void +smbsr_warn(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) +{ + smb_error_t err; + + err.severity = ERROR_SEVERITY_WARNING; + err.status = status; + err.errcls = errcls; + err.errcode = errcode; - sr->smb_rcls = ERRSRV; - sr->smb_err = ERRerror; - return (-1); + smbsr_set_error(sr, &err); } +/* + * Report a request processing error. This function will not return. + */ void -smbsr_raise_errno(struct smb_request *sr, int en) +smbsr_error(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) { - if (smbsr_set_errno(sr, en) != 0) { - if (smb_dispatch_diags) { - cmn_err(CE_NOTE, "SmbErrno: errno=%d", en); - } - } + smb_error_t err; + err.severity = ERROR_SEVERITY_ERROR; + err.status = status; + err.errcls = errcls; + err.errcode = errcode; + + smbsr_set_error(sr, &err); longjmp(&sr->exjb); - /* no return */ + /* NOTREACHED */ +} + +/* + * Setup a request processing error. This function can be used to + * report 32-bit status codes or DOS errors. Set the status code + * to 0 (NT_STATUS_SUCCESS) to explicitly report a DOS error, + * regardless of the client capabilities. + * + * If status is non-zero and the client supports 32-bit status + * codes, report the status. Otherwise, report the DOS error. + */ +void +smbsr_set_error(smb_request_t *sr, smb_error_t *err) +{ + uint32_t status; + uint32_t severity; + uint32_t capabilities; + + ASSERT(sr); + ASSERT(err); + + status = err->status; + severity = (err->severity == 0) ? ERROR_SEVERITY_ERROR : err->severity; + capabilities = sr->session->capabilities; + + if ((err->errcls == 0) && (err->errcode == 0)) { + capabilities |= CAP_STATUS32; + if (status == 0) + status = NT_STATUS_INTERNAL_ERROR; + } + + if ((capabilities & CAP_STATUS32) && (status != 0)) { + status |= severity; + sr->smb_rcls = status & 0xff; + sr->smb_reh = (status >> 8) & 0xff; + sr->smb_err = status >> 16; + sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; + } else { + if ((err->errcls == 0) || (err->errcode == 0)) { + sr->smb_rcls = ERRSRV; + sr->smb_err = ERRerror; + } else { + sr->smb_rcls = (uint8_t)err->errcls; + sr->smb_err = (uint16_t)err->errcode; + } + } } smb_xa_t * diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c index 1492219714..a45e5cab64 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -248,7 +248,7 @@ smb_com_find(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -286,13 +286,13 @@ smb_com_find(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ smb_rdir_close(sr); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { smb_rdir_close(sr); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } @@ -408,7 +408,7 @@ smb_com_find_close(struct smb_request *sr) } if (key_len == 0) { /* begin search */ - smbsr_raise_error(sr, ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -423,7 +423,7 @@ smb_com_find_close(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c index 59f9ba12b2..f9686297f0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -264,13 +264,13 @@ smb_com_find_unique(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_flush.c b/usr/src/uts/common/fs/smbsrv/smb_flush.c index b9cfb8c349..c3da4a2352 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_flush.c +++ b/usr/src/uts/common/fs/smbsrv/smb_flush.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,7 +93,7 @@ smb_com_flush(smb_request_t *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index 3d7292961e..561f640fd1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -19,26 +19,31 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/sid.h> +#include <sys/nbmlock.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smb_kproto.h> #include <smbsrv/smbvar.h> #include <smbsrv/ntstatus.h> #include <smbsrv/ntaccess.h> +#include <smbsrv/smb_incl.h> #include <acl/acl_common.h> - -u_longlong_t smb_caller_id; +#include <sys/fcntl.h> +#include <sys/flock.h> +#include <fs/fs_subr.h> static int smb_fsop_amask_to_omode(uint32_t granted_access); static int smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd); +static callb_cpr_t *smb_fsop_frlock_callback(flk_cb_when_t when, void *error); + /* * The smb_fsop_* functions have knowledge of CIFS semantics. * @@ -65,7 +70,8 @@ smb_fsop_start() { int error; - smb_caller_id = fs_new_caller_id(); + smb_vop_start(); + error = smb_node_root_init(); if (error == 0) @@ -85,32 +91,26 @@ smb_fsop_stop() int smb_fsop_open(smb_ofile_t *of) { - caller_context_t ct; int mode; mode = smb_fsop_amask_to_omode(of->f_granted_access); - smb_get_caller_context(NULL, &ct); - /* * Assuming that same vnode is returned as we had before * (i.e. no special vnodes) */ - return (smb_vop_open(&of->f_node->vp, mode, of->f_cr, &ct)); + return (smb_vop_open(&of->f_node->vp, mode, of->f_cr)); } int smb_fsop_close(smb_ofile_t *of) { - caller_context_t ct; int mode; mode = smb_fsop_amask_to_omode(of->f_granted_access); - smb_get_caller_context(NULL, &ct); - - return (smb_vop_close(of->f_node->vp, mode, of->f_cr, &ct)); + return (smb_vop_close(of->f_node->vp, mode, of->f_cr)); } static int @@ -141,7 +141,6 @@ smb_fsop_create_with_sd( smb_attr_t *ret_attr, smb_fssd_t *fs_sd) { - caller_context_t ct; vsecattr_t *vsap; vsecattr_t vsecattr; acl_t *acl, *dacl, *sacl; @@ -159,7 +158,6 @@ smb_fsop_create_with_sd( flags = SMB_IGNORE_CASE; ASSERT(cr); - smb_get_caller_context(sr, &ct); is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0); @@ -191,10 +189,10 @@ smb_fsop_create_with_sd( if (is_dir) { rc = smb_vop_mkdir(snode->vp, name, attr, &vp, flags, - cr, &ct, vsap); + cr, vsap); } else { rc = smb_vop_create(snode->vp, name, attr, &vp, flags, - cr, &ct, vsap); + cr, vsap); } if (vsap != NULL) @@ -226,7 +224,7 @@ smb_fsop_create_with_sd( if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) no_xvattr = B_TRUE; rc = smb_vop_setattr(snode->vp, NULL, &set_attr, - 0, kcred, no_xvattr, &ct); + 0, kcred, no_xvattr); } } else { @@ -241,10 +239,10 @@ smb_fsop_create_with_sd( if (is_dir) { rc = smb_vop_mkdir(snode->vp, name, attr, &vp, flags, - cr, &ct, NULL); + cr, NULL); } else { rc = smb_vop_create(snode->vp, name, attr, &vp, flags, - cr, &ct, NULL); + cr, NULL); } if (rc != 0) @@ -266,9 +264,9 @@ smb_fsop_create_with_sd( if (rc != 0) { if (is_dir) { - (void) smb_vop_rmdir(snode->vp, name, flags, cr, &ct); + (void) smb_vop_rmdir(snode->vp, name, flags, cr); } else { - (void) smb_vop_remove(snode->vp, name, flags, cr, &ct); + (void) smb_vop_remove(snode->vp, name, flags, cr); } } @@ -303,7 +301,6 @@ smb_fsop_create( struct open_param *op = &sr->arg.open; smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; vnode_t *xattrdirvp; vnode_t *vp; char *longname = NULL; @@ -397,10 +394,8 @@ smb_fsop_create( return (rc); } - smb_get_caller_context(sr, &ct); - rc = smb_vop_stream_create(fnode->vp, sname, attr, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if (rc != 0) { smb_node_release(fnode); @@ -457,9 +452,8 @@ smb_fsop_create( * No incoming SD and filesystem is not ZFS * let the filesystem handles the inheritance. */ - smb_get_caller_context(sr, &ct); rc = smb_vop_create(dir_snode->vp, name, attr, &vp, - flags, cr, &ct, NULL); + flags, cr, NULL); if (rc == 0) { *ret_snode = smb_node_lookup(sr, op, cr, vp, @@ -503,7 +497,6 @@ smb_fsop_mkdir( smb_attr_t *ret_attr) { struct open_param *op = &sr->arg.open; - caller_context_t ct; char *longname; vnode_t *vp; int flags = 0; @@ -511,7 +504,6 @@ smb_fsop_mkdir( uint32_t secinfo; uint32_t status; int rc; - ASSERT(cr); ASSERT(dir_snode); ASSERT(dir_snode->n_magic == SMB_NODE_MAGIC); @@ -557,8 +549,6 @@ smb_fsop_mkdir( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - if (op->sd) { /* * SD sent by client in Windows format. Needs to be @@ -592,7 +582,7 @@ smb_fsop_mkdir( } else { rc = smb_vop_mkdir(dir_snode->vp, name, attr, &vp, flags, cr, - &ct, NULL); + NULL); if (rc == 0) { *ret_snode = smb_node_lookup(sr, op, cr, vp, name, @@ -632,7 +622,6 @@ smb_fsop_remove( { smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; char *longname; char *fname; char *sname; @@ -654,8 +643,6 @@ smb_fsop_remove( if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - smb_get_caller_context(sr, &ct); - fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); @@ -687,7 +674,7 @@ smb_fsop_remove( * Need to find out what permission is required by NTFS * to remove a stream. */ - rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr, &ct); + rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr); smb_node_release(fnode); } else { @@ -705,7 +692,7 @@ smb_fsop_remove( if ((od == 0) && SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - rc = smb_vop_remove(dir_snode->vp, name, flags, cr, &ct); + rc = smb_vop_remove(dir_snode->vp, name, flags, cr); if (rc == ENOENT) { if (smb_maybe_mangled_name(name) == 0) { @@ -729,7 +716,7 @@ smb_fsop_remove( */ flags &= ~SMB_IGNORE_CASE; rc = smb_vop_remove(dir_snode->vp, longname, - flags, cr, &ct); + flags, cr); } kmem_free(longname, MAXNAMELEN); @@ -754,7 +741,6 @@ smb_fsop_remove_streams(struct smb_request *sr, cred_t *cr, smb_node_t *fnode) { struct fs_stream_info stream_info; - caller_context_t ct; uint32_t cookie = 0; int flags = 0; int rc; @@ -773,17 +759,15 @@ smb_fsop_remove_streams(struct smb_request *sr, cred_t *cr, if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - for (;;) { rc = smb_vop_stream_readdir(fnode->vp, &cookie, &stream_info, - NULL, NULL, flags, cr, &ct); + NULL, NULL, flags, cr); if ((rc != 0) || (cookie == SMB_EOF)) break; (void) smb_vop_stream_remove(fnode->vp, stream_info.name, flags, - cr, &ct); + cr); } return (rc); } @@ -809,7 +793,6 @@ smb_fsop_rmdir( char *name, int od) { - caller_context_t ct; int rc; int flags = 0; char *longname; @@ -843,9 +826,7 @@ smb_fsop_rmdir( if ((od == 0) && SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - - rc = smb_vop_rmdir(dir_snode->vp, name, flags, cr, &ct); + rc = smb_vop_rmdir(dir_snode->vp, name, flags, cr); if (rc == ENOENT) { if (smb_maybe_mangled_name(name) == 0) @@ -867,8 +848,7 @@ smb_fsop_rmdir( * a unique directory. */ flags &= ~SMB_IGNORE_CASE; - rc = smb_vop_rmdir(dir_snode->vp, longname, flags, cr, - &ct); + rc = smb_vop_rmdir(dir_snode->vp, longname, flags, cr); } kmem_free(longname, MAXNAMELEN); @@ -893,10 +873,10 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; uint32_t status; uint32_t access = 0; int flags = 0; + int rc; ASSERT(cr); ASSERT(snode); @@ -923,8 +903,6 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, flags = ATTR_NOACLCHECK; } - smb_get_caller_context(sr, &ct); - unnamed_node = SMB_IS_STREAM(snode); if (unnamed_node) { @@ -933,7 +911,11 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, unnamed_vp = unnamed_node->vp; } - return (smb_vop_getattr(snode->vp, unnamed_vp, attr, flags, cr, &ct)); + rc = smb_vop_getattr(snode->vp, unnamed_vp, attr, flags, cr); + if (rc == 0) + snode->attr = *attr; + + return (rc); } /* @@ -959,7 +941,6 @@ smb_fsop_readdir( smb_node_t **ret_snode, smb_attr_t *ret_attr) { - caller_context_t ct; smb_node_t *ret_snodep; smb_node_t *fnode; smb_attr_t tmp_attr; @@ -986,13 +967,11 @@ smb_fsop_readdir( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); if (stream_info) { rc = smb_vop_lookup(dir_snode->vp, name, &fvp, od_name, - SMB_FOLLOW_LINKS, sr->tid_tree->t_snode->vp, cr, &ct); + SMB_FOLLOW_LINKS, sr->tid_tree->t_snode->vp, cr); if (rc != 0) { kmem_free(od_name, MAXNAMELEN); @@ -1017,7 +996,7 @@ smb_fsop_readdir( * Might have to use kcred. */ rc = smb_vop_stream_readdir(fvp, cookie, stream_info, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if ((rc != 0) || (*cookie == SMB_EOF)) { smb_node_release(fnode); @@ -1047,7 +1026,7 @@ smb_fsop_readdir( } else { rc = smb_vop_readdir(dir_snode->vp, cookie, name, namelen, - fileid, &vp, od_name, flags, cr, &ct); + fileid, &vp, od_name, flags, cr); if (rc != 0) { kmem_free(od_name, MAXNAMELEN); @@ -1104,7 +1083,6 @@ smb_fsop_getdents( char *args, char *pattern) { - caller_context_t ct; int flags = 0; ASSERT(cr); @@ -1118,10 +1096,8 @@ smb_fsop_getdents( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - return (smb_vop_getdents(dir_snode, cookie, 0, maxcnt, args, pattern, - flags, sr, cr, &ct)); + flags, sr, cr)); } /* @@ -1145,7 +1121,6 @@ smb_fsop_rename( char *to_name) { smb_node_t *from_snode; - caller_context_t ct; smb_attr_t tmp_attr; vnode_t *from_vp; int flags = 0; @@ -1188,16 +1163,14 @@ smb_fsop_rename( * XXX: Lock required through smb_node_release() below? */ - smb_get_caller_context(sr, &ct); - rc = smb_vop_lookup(from_dir_snode->vp, from_name, &from_vp, NULL, 0, - NULL, cr, &ct); + NULL, cr); if (rc != 0) return (rc); rc = smb_vop_rename(from_dir_snode->vp, from_name, to_dir_snode->vp, - to_name, flags, cr, &ct); + to_name, flags, cr); if (rc == 0) { from_snode = smb_node_lookup(sr, NULL, cr, from_vp, from_name, @@ -1242,7 +1215,6 @@ smb_fsop_setattr( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; uint32_t status; uint32_t access = 0; int rc = 0; @@ -1278,8 +1250,6 @@ smb_fsop_setattr( flags = ATTR_NOACLCHECK; } - smb_get_caller_context(sr, &ct); - unnamed_node = SMB_IS_STREAM(snode); if (unnamed_node) { @@ -1291,18 +1261,18 @@ smb_fsop_setattr( if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) no_xvattr = B_TRUE; - rc = smb_vop_setattr(snode->vp, unnamed_vp, - set_attr, flags, cr, no_xvattr, &ct); + rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr, + no_xvattr); if ((rc == 0) && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + rc = smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, kcred); + if (rc == 0) + snode->attr = *ret_attr; } return (rc); @@ -1328,7 +1298,7 @@ smb_fsop_read( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; + int svmand; int rc; ASSERT(cr); @@ -1360,20 +1330,36 @@ smb_fsop_read( cr = kcred; } - smb_get_caller_context(sr, &ct); - rc = smb_vop_read(snode->vp, uio, cr, &ct); + smb_node_start_crit(snode, RW_READER); + rc = nbl_svmand(snode->vp, cr, &svmand); + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + + rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset, + uio->uio_iov->iov_len, svmand, &smb_ct); - if (rc == 0) { + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = smb_vop_read(snode->vp, uio, cr); + + if (rc == 0 && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + if (smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, + kcred) == 0) { + snode->attr = *ret_attr; + } } + smb_node_end_crit(snode); + return (rc); } @@ -1396,7 +1382,7 @@ smb_fsop_write( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; + int svmand; int rc; ASSERT(cr); @@ -1410,15 +1396,13 @@ smb_fsop_write( if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - /* - * XXX what if the file has been opened only with - * FILE_APPEND_DATA? - */ - rc = smb_ofile_access(sr->fid_ofile, cr, FILE_WRITE_DATA); - if (rc != NT_STATUS_SUCCESS) - return (EACCES); - smb_get_caller_context(sr, &ct); + rc = smb_ofile_access(sr->fid_ofile, cr, FILE_WRITE_DATA); + if (rc != NT_STATUS_SUCCESS) { + rc = smb_ofile_access(sr->fid_ofile, cr, FILE_APPEND_DATA); + if (rc != NT_STATUS_SUCCESS) + return (EACCES); + } unnamed_node = SMB_IS_STREAM(snode); @@ -1435,19 +1419,35 @@ smb_fsop_write( cr = kcred; } - rc = smb_vop_write(snode->vp, uio, flag, lcount, cr, &ct); + smb_node_start_crit(snode, RW_READER); + rc = nbl_svmand(snode->vp, cr, &svmand); + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = nbl_lock_conflict(snode->vp, NBL_WRITE, uio->uio_loffset, + uio->uio_iov->iov_len, svmand, &smb_ct); - if (rc == 0) { + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = smb_vop_write(snode->vp, uio, flag, lcount, cr); + + if (rc == 0 && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + if (smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, + kcred) == 0) { + snode->attr = *ret_attr; + } } + smb_node_end_crit(snode); + return (rc); } @@ -1577,7 +1577,6 @@ smb_fsop_lookup_name( { smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; vnode_t *xattrdirvp; vnode_t *vp; char *od_name; @@ -1627,7 +1626,7 @@ smb_fsop_lookup_name( * What permissions NTFS requires for stream lookup if any? */ rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name, - &xattrdirvp, flags, root_node->vp, cr, &ct); + &xattrdirvp, flags, root_node->vp, cr); if (rc != 0) { smb_node_release(fnode); @@ -1707,7 +1706,6 @@ smb_fsop_lookup( { smb_node_t *lnk_target_node; smb_node_t *lnk_dnode; - caller_context_t ct; char *longname; char *od_name; vnode_t *vp; @@ -1727,12 +1725,10 @@ smb_fsop_lookup( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags |= SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); rc = smb_vop_lookup(dir_snode->vp, name, &vp, od_name, flags, - root_node ? root_node->vp : NULL, cr, &ct); + root_node ? root_node->vp : NULL, cr); if (rc != 0) { if (smb_maybe_mangled_name(name) == 0) { @@ -1764,7 +1760,7 @@ smb_fsop_lookup( flags &= ~SMB_IGNORE_CASE; rc = smb_vop_lookup(dir_snode->vp, longname, &vp, od_name, - flags, root_node ? root_node->vp : NULL, cr, &ct); + flags, root_node ? root_node->vp : NULL, cr); kmem_free(longname, MAXNAMELEN); @@ -1871,7 +1867,6 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, smb_node_t **ret_snode, smb_attr_t *ret_attr) { smb_node_t *ret_snodep = NULL; - caller_context_t ct; smb_attr_t tmp_attr; vnode_t *xattrdirvp; vnode_t *vp; @@ -1889,10 +1884,8 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - rc = smb_vop_stream_readdir(fnode->vp, cookiep, stream_info, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if ((rc != 0) || *cookiep == SMB_EOF) return (rc); @@ -1922,8 +1915,6 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, int /*ARGSUSED*/ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode) { - caller_context_t ct; - ASSERT(cr); ASSERT(snode); ASSERT(snode->n_magic == SMB_NODE_MAGIC); @@ -1934,9 +1925,7 @@ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode) if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - smb_get_caller_context(sr, &ct); - - return (smb_vop_commit(snode->vp, cr, &ct)); + return (smb_vop_commit(snode->vp, cr)); } /* @@ -1961,7 +1950,6 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, int flags = 0; int access = 0; acl_t *acl; - caller_context_t ct; smb_node_t *unnamed_node; ASSERT(cr); @@ -1993,9 +1981,8 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, if (sr->tid_tree->t_flags & SMB_TREE_FLAG_ACEMASKONACCESS) flags = ATTR_NOACLCHECK; - smb_get_caller_context(sr, &ct); error = smb_vop_acl_read(snode->vp, &acl, flags, - sr->tid_tree->t_acltype, cr, &ct); + sr->tid_tree->t_acltype, cr); if (error != 0) { return (error); } @@ -2025,7 +2012,6 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, int error = 0; int flags = 0; int access = 0; - caller_context_t ct; acl_t *acl, *dacl, *sacl; smb_node_t *unnamed_node; @@ -2088,11 +2074,10 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, error = acl_translate(acl, target_flavor, (snode->vp->v_type == VDIR), fs_sd->sd_uid, fs_sd->sd_gid); if (error == 0) { - smb_get_caller_context(sr, &ct); if (sr->tid_tree->t_flags & SMB_TREE_FLAG_ACEMASKONACCESS) flags = ATTR_NOACLCHECK; - error = smb_vop_acl_write(snode->vp, acl, flags, cr, &ct); + error = smb_vop_acl_write(snode->vp, acl, flags, cr); } if (dacl && sacl) @@ -2474,11 +2459,131 @@ smb_fsop_eaccess(smb_request_t *sr, cred_t *cr, smb_node_t *snode, FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD; } -/*ARGSUSED*/ +/* + * smb_fsop_shrlock + * + * For the current open request, check file sharing rules + * against existing opens. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict. Returns NT_STATUS_SUCCESS otherwise. + * + * Full system-wide share reservation synchronization is available + * when the nbmand (non-blocking mandatory) mount option is set + * (i.e. nbl_need_crit() is true) and nbmand critical regions are used. + * This provides synchronization with NFS and local processes. The + * critical regions are entered in VOP_SHRLOCK()/fs_shrlock() (called + * from smb_open_subr()/smb_fsop_shrlock()/smb_vop_shrlock()) as well + * as the CIFS rename and delete paths. + * + * The CIFS server will also enter the nbl critical region in the open, + * rename, and delete paths when nbmand is not set. There is limited + * coordination with local and VFS share reservations in this case. + * Note that when the nbmand mount option is not set, the VFS layer + * only processes advisory reservations and the delete mode is not checked. + * + * Whether or not the nbmand mount option is set, intra-CIFS share + * checking is done in the open, delete, and rename paths using a CIFS + * critical region (node->n_share_lock). + */ + +uint32_t +smb_fsop_shrlock(cred_t *cr, struct smb_node *node, uint32_t uniq_fid, + uint32_t desired_access, uint32_t share_access) +{ + int rc; + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + /* Allow access if the request is just for meta data */ + if ((desired_access & FILE_DATA_ALL) == 0) + return (NT_STATUS_SUCCESS); + + rc = smb_node_open_check(node, cr, desired_access, share_access); + if (rc) + return (NT_STATUS_SHARING_VIOLATION); + + rc = smb_vop_shrlock(node->vp, uniq_fid, desired_access, share_access, + cr); + if (rc) + return (NT_STATUS_SHARING_VIOLATION); + + return (NT_STATUS_SUCCESS); +} + void -smb_get_caller_context(smb_request_t *sr, caller_context_t *ct) +smb_fsop_unshrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid) +{ + if (node->attr.sa_vattr.va_type == VDIR) + return; + + (void) smb_vop_unshrlock(node->vp, uniq_fid, cr); +} + +/* + * smb_fsop_frlock_callback + * + * smb wrapper function for fs_frlock + * this should never happen, as we are not attempting + * to set Mandatory Locks, cmd = F_SETLK_NBMAND + * + */ + +static callb_cpr_t * +/* ARGSUSED */ +smb_fsop_frlock_callback(flk_cb_when_t when, void *error) { - ct->cc_caller_id = smb_caller_id; - ct->cc_pid = 0; /* TBD */ - ct->cc_sysid = 0; /* TBD */ + return (0); +} + +/* + * smb_fs_frlock + * + * smb wrapper function for fs_frlock + */ + +int +smb_fsop_frlock(smb_request_t *sr, smb_node_t *node, smb_lock_t *lock, + boolean_t unlock) +{ + vnode_t *vp; + flock64_t bf; + cred_t *cr; + caller_context_t *ct; + int cmd; + flk_callback_t flk_cb; + offset_t offset = 0; + int flag; + int error; + int i; + + flk_init_callback(&flk_cb, smb_fsop_frlock_callback, &error); + cr = sr->user_cr; + ct = &smb_ct; + vp = node->vp; + cmd = F_SETLK; + + if (unlock == B_TRUE) { + bf.l_type = F_UNLCK; + flag = 0; + } else if (lock->l_type == SMB_LOCK_TYPE_READONLY) { + bf.l_type = F_RDLCK; + flag = FREAD; + } else if (lock->l_type == SMB_LOCK_TYPE_READWRITE) { + bf.l_type = F_WRLCK; + flag = FWRITE; + } + + bf.l_start = lock->l_start; + bf.l_len = lock->l_length; + bf.l_whence = 0; /* SEEK_SET */ + bf.l_pid = lock->l_pid; + bf.l_sysid = 0; + + for (i = 0; i < 4; i++) + bf.l_pad[i] = 0; + + error = fs_frlock(vp, cmd, &bf, flag, offset, &flk_cb, cr, ct); + return (error); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c index cb5aa042ee..d9773cb50f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,7 +76,7 @@ smb_com_lock_byte_range(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -90,7 +90,7 @@ smb_com_lock_byte_range(struct smb_request *sr) result = smb_lock_range(sr, sr->fid_ofile, (u_offset_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c index 7326d5a12c..b39188ebbd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,17 @@ */ #include <smbsrv/smb_incl.h> +#include <smbsrv/smb_fsops.h> +#include <sys/nbmlock.h> +#include <sys/param.h> + +static void +smb_unlock_to_posix_unlock(smb_request_t *sr, smb_node_t *node, + smb_lock_t *lock, boolean_t unlock); + +static boolean_t +smb_is_range_unlocked(uint64_t start, uint64_t end, smb_llist_t *llist_head, + uint64_t *new_mark); static int smb_lock_range_overlap(struct smb_lock *lock, uint64_t start, uint64_t length); @@ -367,6 +378,9 @@ smb_unlock_range( } smb_llist_remove(&node->n_lock_list, lock); + + smb_unlock_to_posix_unlock(sr, node, lock, B_TRUE); + smb_llist_exit(&node->n_lock_list); smb_lock_destroy(lock); @@ -481,7 +495,14 @@ smb_lock_range( smb_lock_free(lock); } else { - smb_llist_insert_tail(&node->n_lock_list, lock); + /* + * don't insert into the CIFS lock list unless the + * posix lock worked + */ + if (smb_fsop_frlock(sr, node, lock, B_FALSE)) + result = NT_STATUS_FILE_LOCK_CONFLICT; + else + smb_llist_insert_tail(&node->n_lock_list, lock); } smb_llist_exit(&node->n_lock_list); @@ -506,15 +527,12 @@ smb_lock_range_access( struct smb_node *node, uint64_t start, uint64_t length, - uint32_t desired_access) + boolean_t will_write) { smb_lock_t *lock; smb_llist_t *llist; int status = NT_STATUS_SUCCESS; - ASSERT((desired_access & ~(FILE_READ_DATA | FILE_WRITE_DATA)) == 0); - ASSERT((desired_access & (FILE_READ_DATA | FILE_WRITE_DATA)) != 0); - llist = &node->n_lock_list; smb_llist_enter(llist, RW_READER); /* Search for any applicable lock */ @@ -526,8 +544,7 @@ smb_lock_range_access( /* Lock does not overlap */ continue; - if (lock->l_type == SMB_LOCK_TYPE_READONLY && - desired_access == FILE_READ_DATA) + if (lock->l_type == SMB_LOCK_TYPE_READONLY && !will_write) continue; if (lock->l_type == SMB_LOCK_TYPE_READWRITE && @@ -664,46 +681,196 @@ smb_node_destroy_lock_by_ofile(smb_node_t *node, smb_ofile_t *file) } void -smb_lock_range_raise_error(smb_request_t *sr, uint32_t ntstatus) +smb_lock_range_error(smb_request_t *sr, uint32_t status32) { - switch (ntstatus) { - case NT_STATUS_CANCELLED: - /* - * XXX What is the proper error here? - */ - smbsr_raise_error(sr, ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_FILE_LOCK_CONFLICT: - smbsr_raise_cifs_error(sr, NT_STATUS_FILE_LOCK_CONFLICT, - ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_LOCK_NOT_GRANTED: - smbsr_raise_cifs_error(sr, NT_STATUS_LOCK_NOT_GRANTED, - ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_RANGE_NOT_LOCKED: - smbsr_raise_cifs_error(sr, NT_STATUS_RANGE_NOT_LOCKED, - ERRDOS, ERRlock); - /* NOTREACHED */ - default: - ASSERT(0); - smbsr_raise_error(sr, ERRDOS, ntstatus); - /* NOTREACHED */ + uint16_t errcode; + + if (status32 == NT_STATUS_CANCELLED) + errcode = ERROR_OPERATION_ABORTED; + else + errcode = ERRlock; + + smbsr_error(sr, status32, ERRDOS, errcode); + /* NOTREACHED */ +} + +/* + * smb_range_check() + * + * Perform range checking. First check for internal CIFS range conflicts + * and then check for external conflicts, for example, with NFS or local + * access. + * + * If nbmand is enabled, this function must be called from within an nbmand + * critical region + */ + +DWORD +smb_range_check(smb_request_t *sr, cred_t *cr, smb_node_t *node, uint64_t start, + uint64_t length, boolean_t will_write) +{ + smb_error_t smberr; + int svmand; + int nbl_op; + int rc; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + ASSERT(smb_node_in_crit(node)); + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + rc = smb_lock_range_access(sr, node, start, length, will_write); + if (rc) + return (NT_STATUS_UNSUCCESSFUL); + + if ((rc = nbl_svmand(node->vp, cr, &svmand)) != 0) { + smbsr_map_errno(rc, &smberr); + return (smberr.status); } + + if (will_write) + nbl_op = NBL_WRITE; + else + nbl_op = NBL_READ; + + if (nbl_lock_conflict(node->vp, nbl_op, start, length, + svmand, &smb_ct)) + return (NT_STATUS_UNSUCCESSFUL); + + return (NT_STATUS_SUCCESS); } +/* + * smb_unlock_to_posix_unlock + * + * checks if the current unlock request is in another lock + * and repeatedly calls smb_is_range_unlocked on a sliding basis to + * to unlock all bits of the lock that are not in other locks + * + */ void -smb_unlock_range_raise_error(smb_request_t *sr, uint32_t ntstatus) +smb_unlock_to_posix_unlock(smb_request_t *sr, smb_node_t *node, + smb_lock_t *lock, boolean_t unlock) { - switch (ntstatus) { - case NT_STATUS_RANGE_NOT_LOCKED: - smbsr_raise_cifs_error(sr, NT_STATUS_RANGE_NOT_LOCKED, - ERRDOS, ERRnotlocked); - /* NOTREACHED */ - default: - ASSERT(0); - smbsr_raise_error(sr, ERRDOS, ntstatus); - /* NOTREACHED */ + uint64_t new_mark; + uint64_t unlock_start; + uint64_t unlock_end; + boolean_t unlocked; + smb_lock_t new_unlock; + smb_llist_t *llist_head; + int cnt = 1; + + new_mark = 0; + unlock_start = lock->l_start; + unlock_end = unlock_start + lock->l_length; + llist_head = &node->n_lock_list; + + while (cnt) { + if ((unlocked = smb_is_range_unlocked(unlock_start, unlock_end, + llist_head, &new_mark)) == B_TRUE) { + if (new_mark) { + new_unlock = *lock; + new_unlock.l_start = unlock_start; + new_unlock.l_length = new_mark - unlock_start; + (void) smb_fsop_frlock(sr, node, + &new_unlock, unlock); + unlock_start = new_mark; + } else { + new_unlock = *lock; + new_unlock.l_start = unlock_start; + new_unlock.l_length = unlock_end - unlock_start; + (void) smb_fsop_frlock(sr, node, + &new_unlock, unlock); + break; + } + } else if ((unlocked == B_FALSE) && new_mark) { + unlock_start = new_mark; + } else { + break; + } + } +} + +/* + * smb_is_range_unlocked + * + * Checks if the current unlock byte range request overlaps another lock + * The return code and the value of new_mark must be interpreted as + * follows: + * + * B_TRUE and (new_mark == 0): + * This is the last or only lock left to be unlocked + * + * B_TRUE and (new_mark > 0): + * The range from start to new_mark can be unlocked + * + * B_FALSE and (new_mark == 0): + * The unlock can't be performed and we are done + * + * B_FALSE and (new_mark > 0), + * The range from start to new_mark can't be unlocked + * Start should be reset to new_mark for the next pass + */ + +static boolean_t +smb_is_range_unlocked(uint64_t start, uint64_t end, smb_llist_t *llist_head, + uint64_t *new_mark) +{ + struct smb_lock *lk = 0; + uint64_t low_water_mark = MAXOFFSET_T; + uint64_t lk_start; + uint64_t lk_end; + + *new_mark = 0; + lk = smb_llist_head(llist_head); + while (lk) { + + lk_end = lk->l_start + lk->l_length - 1; + lk_start = lk->l_start; + + /* + * there is no overlap for the first 2 cases + * check next node + */ + if (lk_end < start) { + lk = smb_llist_next(llist_head, lk); + continue; + } + if (lk_start > end) { + lk = smb_llist_next(llist_head, lk); + continue; + } + + /* this range is completely locked */ + if ((lk_start <= start) && (lk_end >= end)) { + return (B_FALSE); + } + + /* the first part of this range is locked */ + if ((start >= lk_start) && (start <= lk_end)) { + if (end > lk_end) + *new_mark = lk_end + 1; + return (B_FALSE); + } + + /* this piece is unlocked */ + if ((lk_start >= start) && (lk_start <= end)) { + if (low_water_mark > lk_start) + low_water_mark = lk_start; + } + + lk = smb_llist_next(llist_head, lk); + } + + if (low_water_mark != MAXOFFSET_T) { + *new_mark = low_water_mark; + return (B_TRUE); } + /* the range is completely unlocked */ + return (B_TRUE); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c index 0acf7922c4..4aa585091e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -239,8 +239,7 @@ smb_com_locking_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -275,7 +274,7 @@ smb_com_locking_andx(struct smb_request *sr) * implement this) */ if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) { - smbsr_raise_error(sr, ERRDOS, ERRnoatomiclocks); + smbsr_error(sr, 0, ERRDOS, ERRnoatomiclocks); /* NOT REACHED */ } @@ -283,8 +282,7 @@ smb_com_locking_andx(struct smb_request *sr) * No support for cancel lock (smbtorture expects this) */ if (lock_type & LOCKING_ANDX_CANCEL_LOCK) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOT REACHED */ } @@ -294,8 +292,7 @@ smb_com_locking_andx(struct smb_request *sr) * negotiated protocol should be NT LM 0.12 or later */ if (sr->session->dialect < NT_LM_0_12) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOT REACHED */ } @@ -305,17 +302,18 @@ smb_com_locking_andx(struct smb_request *sr) &sr->smb_pid, &offset64, &length64); if (rc) { /* - * This is the error returned by a W2K system - * even when NT Status is negotiated. + * This is the error returned by Windows 2000 + * even when STATUS32 has been negotiated. */ - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, offset64, length64); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } } @@ -324,14 +322,14 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "w2.QQ", &sr->smb_pid, &offset64, &length64); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_lock_range(sr, sr->fid_ofile, offset64, length64, timeout, ltype); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } } @@ -340,14 +338,15 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, &offset32, &length32); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, (uint64_t)offset32, (uint64_t)length32); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } } @@ -356,7 +355,7 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, &offset32, &length32); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } @@ -365,7 +364,7 @@ smb_com_locking_andx(struct smb_request *sr) (uint64_t)length32, timeout, ltype); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c index 278916b8fd..4b56c61b73 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,8 +66,7 @@ int smb_com_logoff_andx(struct smb_request *sr) { if (sr->uid_user == NULL) { - cmn_err(CE_WARN, "SmbLogoffAndX: bad uid"); - smbsr_raise_error(sr, ERRSRV, ERRbaduid); + smbsr_error(sr, 0, ERRSRV, ERRbaduid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c index 844e84a889..a14ae7d3a5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c +++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -261,7 +261,7 @@ smb_com_negotiate(struct smb_request *sr) if (sr->session->s_state != SMB_SESSION_STATE_ESTABLISHED) { /* The protocol has already been negotiated. */ - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -269,7 +269,7 @@ smb_com_negotiate(struct smb_request *sr) sr->smb_data.chain_offset < sr->smb_data.max_bytes; pos++) { if (smb_decode_mbc(&sr->smb_data, "%L", sr, &p) != 0) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -284,7 +284,7 @@ smb_com_negotiate(struct smb_request *sr) } } if (sel_pos < 0) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -435,9 +435,7 @@ smb_com_negotiate(struct smb_request *sr) break; default: - /* Just to make sure. */ - ASSERT(0); - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c index 5ea8c5f1c3..13be0f3cf3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_node.c +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,6 +84,7 @@ #include <smbsrv/smb_fsops.h> #include <sys/pathname.h> #include <sys/sdt.h> +#include <sys/nbmlock.h> uint32_t smb_is_executable(char *path); static void smb_node_delete_on_close(smb_node_t *node); @@ -138,7 +139,6 @@ smb_node_lookup( fs_desc_t fsd; int error; krw_t lock_mode; - caller_context_t ct; vnode_t *unnamed_vp = NULL; /* @@ -154,9 +154,8 @@ smb_node_lookup( * This getattr is performed on behalf of the server * that's why kcred is used not the user's cred */ - smb_get_caller_context(sr, &ct); attr->sa_mask = SMB_AT_ALL; - error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred, &ct); + error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred); if (error) return (NULL); @@ -208,6 +207,7 @@ smb_node_lookup( smb_node_ref(dir_snode); } node->attr = *attr; + node->n_size = attr->sa_vattr.va_size; smb_audit_node(node); smb_rwx_xexit(&node->n_lock); @@ -768,3 +768,252 @@ smb_node_reset_delete_on_close(smb_node_t *node) } smb_rwx_xexit(&node->n_lock); } + +/* + * smb_node_share_check + * + * check file sharing rules for current open request + * against all existing opens for a file. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict, otherwise returns NT_STATUS_SUCCESS. + */ +uint32_t +smb_node_open_check(struct smb_node *node, cred_t *cr, + uint32_t desired_access, uint32_t share_access) +{ + smb_ofile_t *of; + uint32_t status; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + smb_llist_enter(&node->n_ofile_list, RW_READER); + of = smb_llist_head(&node->n_ofile_list); + while (of) { + status = smb_node_share_check(node, cr, desired_access, + share_access, of); + if (status == NT_STATUS_SHARING_VIOLATION) { + smb_llist_exit(&node->n_ofile_list); + return (status); + } + of = smb_llist_next(&node->n_ofile_list, of); + } + smb_llist_exit(&node->n_ofile_list); + + return (NT_STATUS_SUCCESS); +} + +/* + * smb_open_share_check + * + * check file sharing rules for current open request + * against the given existing open. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict, otherwise returns NT_STATUS_SUCCESS. + */ +uint32_t +smb_node_share_check( + struct smb_node *node, + cred_t *cr, + uint32_t desired_access, + uint32_t share_access, + smb_ofile_t *of) +{ + /* + * It appears that share modes are not relevant to + * directories, but this check will remain as it is not + * clear whether it was originally put here for a reason. + */ + if (node->attr.sa_vattr.va_type == VDIR) { + if (SMB_DENY_RW(of->f_share_access) && + (node->n_orig_uid != crgetuid(cr))) { + return (NT_STATUS_SHARING_VIOLATION); + } + + return (NT_STATUS_SUCCESS); + } + + /* if it's just meta data */ + if ((of->f_granted_access & FILE_DATA_ALL) == 0) + return (NT_STATUS_SUCCESS); + + /* + * Check requested share access against the + * open granted (desired) access + */ + if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_READ(share_access) && + (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_WRITE(share_access) && + (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) + return (NT_STATUS_SHARING_VIOLATION); + + /* check requested desired access against the open share access */ + if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_READ(of->f_share_access) && + (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_WRITE(of->f_share_access) && + (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) + return (NT_STATUS_SHARING_VIOLATION); + + return (NT_STATUS_SUCCESS); +} + +/* + * smb_rename_share_check + * + * An open file can be renamed if + * + * 1. isn't opened for data writing or deleting + * + * 2. Opened with "Deny Delete" share mode + * But not opened for data reading or executing + * (opened for accessing meta data) + */ + +DWORD +smb_node_rename_check(struct smb_node *node) +{ + struct smb_ofile *open; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + /* + * Intra-CIFS check + */ + + smb_llist_enter(&node->n_ofile_list, RW_READER); + open = smb_llist_head(&node->n_ofile_list); + while (open) { + if (open->f_granted_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + + if ((open->f_share_access & FILE_SHARE_DELETE) == 0) { + if (open->f_granted_access & + (FILE_READ_DATA | FILE_EXECUTE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + } + open = smb_llist_next(&node->n_ofile_list, open); + } + smb_llist_exit(&node->n_ofile_list); + + /* + * system-wide share check + */ + + if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) + return (NT_STATUS_SHARING_VIOLATION); + else + return (NT_STATUS_SUCCESS); +} + +/* + * smb_node_delete_check + * + * An open file can be deleted only if opened for + * accessing meta data. Share modes aren't important + * in this case. + * + * NOTE: there is another mechanism for deleting an + * open file that NT clients usually use. + * That's setting "Delete on close" flag for an open + * file. In this way the file will be deleted after + * last close. This flag can be set by SmbTrans2SetFileInfo + * with FILE_DISPOSITION_INFO information level. + * For setting this flag, the file should be opened by + * DELETE access in the FID that is passed in the Trans2 + * request. + */ +DWORD +smb_node_delete_check(smb_node_t *node) +{ + smb_ofile_t *file; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + /* + * intra-CIFS check + */ + + smb_llist_enter(&node->n_ofile_list, RW_READER); + file = smb_llist_head(&node->n_ofile_list); + while (file) { + ASSERT(file->f_magic == SMB_OFILE_MAGIC); + if (file->f_granted_access & + (FILE_READ_DATA | + FILE_WRITE_DATA | + FILE_APPEND_DATA | + FILE_EXECUTE | + DELETE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + file = smb_llist_next(&node->n_ofile_list, file); + } + smb_llist_exit(&node->n_ofile_list); + + /* + * system-wide share check + */ + + if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) + return (NT_STATUS_SHARING_VIOLATION); + else + return (NT_STATUS_SUCCESS); +} + +/* + * smb_node_start_crit() + * + * Enter critical region for share reservations. + * See comments above smb_fsop_shrlock(). + */ + +void +smb_node_start_crit(smb_node_t *node, krw_t mode) +{ + rw_enter(&node->n_share_lock, mode); + nbl_start_crit(node->vp, mode); +} + +/* + * smb_node_end_crit() + * + * Exit critical region for share reservations. + */ + +void +smb_node_end_crit(smb_node_t *node) +{ + nbl_end_crit(node->vp); + rw_exit(&node->n_share_lock); +} + +int +smb_node_in_crit(smb_node_t *node) +{ + return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_share_lock)); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c index 36a3df5992..e7dbe26746 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -206,7 +206,7 @@ smb_com_nt_create_andx(struct smb_request *sr) } if (NameLength >= MAXPATHLEN) { - smbsr_raise_nt_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND); + smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, 0, 0); /* NOTREACHED */ } @@ -217,7 +217,7 @@ smb_com_nt_create_andx(struct smb_request *sr) if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } @@ -253,7 +253,7 @@ smb_com_nt_create_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -284,11 +284,10 @@ smb_com_nt_create_andx(struct smb_request *sr) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c index 00d648cc32..d844733b36 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -115,14 +115,14 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } if (sd_len) { status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } op->sd = &sd; @@ -177,11 +177,10 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c index 5725814a0f..16fbdbede8 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +90,7 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) &fid, &is_fsctl, &is_flags) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); } for (i = 0; @@ -103,7 +103,7 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) } if (status != NT_STATUS_SUCCESS) - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); (void) smb_encode_mbc(&xa->rep_param_mb, "l", 0); return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c index d70ddf4fc0..264a078a48 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,8 +135,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -144,10 +143,9 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) if (node->attr.sa_vattr.va_type != VDIR) { /* - * notify change requests are only valid for - * directories + * Notify change requests are only valid on directories. */ - smbsr_raise_nt_error(sr, NT_STATUS_NOT_A_DIRECTORY); + smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, 0, 0); /* NOTREACHED */ } @@ -192,7 +190,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) case SMB_REQ_STATE_CANCELED: mutex_exit(&sr->sr_mutex); - smbsr_raise_nt_error(sr, NT_STATUS_CANCELLED); + smbsr_error(sr, NT_STATUS_CANCELLED, 0, 0); /* NOTREACHED */ default: ASSERT(0); @@ -211,13 +209,13 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) * is sent in reply. */ int -smb_reply_notify_change_request( - smb_request_t *sr) +smb_reply_notify_change_request(smb_request_t *sr) { smb_node_t *node; int total_bytes, n_setup, n_param, n_data; int param_off, param_pad, data_off, data_pad; struct smb_xa *xa; + smb_error_t err; xa = sr->r_xa; node = sr->sr_ncr.nc_node; @@ -273,12 +271,12 @@ smb_reply_notify_change_request( break; case SMB_REQ_STATE_CANCELED: - /* - * an STATUS should be sent, - * we need an implementation of nt_raise_error - * but without long jump. - */ - smbsr_setup_nt_status(sr, 0xc0000000, NT_STATUS_CANCELLED); + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_CANCELLED; + err.errcls = ERRDOS; + err.errcode = ERROR_OPERATION_ABORTED; + smbsr_set_error(sr, &err); + (void) smb_encode_mbc(&sr->reply, "bwbw", (short)0, 0L, (short)0, 0L); sr->smb_wct = 0; diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c index fec95a2835..69ea40bdb3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,25 +74,24 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) uint32_t secinfo; uint32_t sdlen; uint32_t status; - + smb_error_t err; if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -107,14 +106,14 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_sd_read(sr, &sd, secinfo); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } sdlen = smb_sd_len(&sd, secinfo); if (sdlen == 0) { smb_sd_term(&sd); - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_SECURITY_DESCR); + smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0); /* NOTREACHED */ } @@ -126,8 +125,11 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) * should provide a buffer size hint for the client. */ (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); - smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, - NT_STATUS_BUFFER_TOO_SMALL); + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_BUFFER_TOO_SMALL; + err.errcls = ERRDOS; + err.errcode = ERROR_INSUFFICIENT_BUFFER; + smbsr_set_error(sr, &err); smb_sd_term(&sd); return (SDRC_NORMAL_REPLY); } @@ -166,25 +168,24 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { - smbsr_raise_nt_error(sr, NT_STATUS_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); /* NOTREACHED */ } if (sr->fid_ofile->f_node->flags & NODE_READ_ONLY) { - smbsr_raise_nt_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED); + smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); /* NOTREACHED */ } @@ -202,20 +203,20 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } status = smb_sd_write(sr, &sd, secinfo); smb_sd_term(&sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index e8eb106291..fa9631336b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -186,6 +186,7 @@ smb_ofile_open( uint16_t ftype, char *pipe_name, uint32_t rpc_fid, + uint32_t uniqid, smb_error_t *err) { smb_ofile_t *of; @@ -203,6 +204,7 @@ smb_ofile_open( of->f_magic = SMB_OFILE_MAGIC; of->f_refcnt = 1; of->f_fid = fid; + of->f_uniqid = uniqid; of->f_opened_by_pid = pid; of->f_granted_access = access_granted; of->f_share_access = share_access; @@ -271,7 +273,6 @@ smb_ofile_close( { int rc = 0; - ASSERT(of); ASSERT(of->f_magic == SMB_OFILE_MAGIC); @@ -286,9 +287,6 @@ smb_ofile_close( if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { smb_rpc_close(of); } else { - if (of->f_node->vp->v_type == VREG) - (void) smb_fsop_close(of); - if (of->f_node->flags & NODE_CREATED_READONLY) { smb_node_set_dosattr(of->f_node, of->f_node->attr.sa_dosattr | @@ -300,12 +298,20 @@ smb_ofile_close( rc = smb_sync_fsattr(NULL, of->f_cr, of->f_node); smb_commit_delete_on_close(of); smb_release_oplock(of, OPLOCK_RELEASE_FILE_CLOSED); - smb_commit_delete_on_close(of); + + /* + * Share reservations cannot be removed until the + * readonly bit has been set (if needed), above. + * See comments in smb_open_subr(). + */ + smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); + + if (of->f_node->vp->v_type == VREG) + (void) smb_fsop_close(of); + /* - * if there is any notify change request for - * this file then see if any of them is related - * to this open instance. If there is any then - * cancel them. + * Cancel any notify change requests related + * to this open instance. */ if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE) smb_process_file_notify_change_queue(of); diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c index b195ed6353..486422d9c5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -245,7 +245,7 @@ smb_com_open(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -266,11 +266,10 @@ smb_com_open(struct smb_request *sr) if ((status = smb_open_subr(sr)) != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } @@ -281,7 +280,7 @@ smb_com_open(struct smb_request *sr) } if (op->dsize > UINT_MAX) - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); file_attr = op->dattr & FILE_ATTRIBUTE_MASK; @@ -330,7 +329,7 @@ smb_com_open_andx(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -338,7 +337,7 @@ smb_com_open_andx(struct smb_request *sr) op->dattr = file_attr; op->create_disposition = smb_ofun_to_crdisposition(ofun); if (op->create_disposition == ((uint32_t)SMB_INVALID_CRDISPOSITION)) { - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_PARAMETER); + smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -376,17 +375,16 @@ smb_com_open_andx(struct smb_request *sr) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } if (op->dsize > UINT_MAX) - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); if (MYF_OPLOCK_TYPE(op->my_flags) != MYF_OPLOCK_NONE) { op->action_taken |= SMB_OACT_LOCK; diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c index cc203a7315..c31c764bf4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c +++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,10 +59,6 @@ smb_is_executable(char *path) /* * smbd_fs_query * - * This function has been changed to return errors instead of using - * smbsr_raise_errno to longjmp round the calling code. This allows - * the caller to release resources when an error occurs. - * * Upon success, the caller will need to call smb_node_release() on * fqi.last_snode (if it isn't already set to NULL by this routine) and * and fqi.dir_snode. These pointers will not be used after the caller diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information.c b/usr/src/uts/common/fs/smbsrv/smb_query_information.c index 8cb636aaa9..391c3f9c24 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -95,7 +95,7 @@ smb_com_query_information(struct smb_request *sr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -103,7 +103,7 @@ smb_com_query_information(struct smb_request *sr) sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0)) != 0) { smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c index a1324aa74e..d6fa3d1f26 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,15 +76,13 @@ smb_com_query_information2(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { - cmn_err(CE_NOTE, "SmbQueryInfo2: access denied"); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c index 4c69d8516e..6e38758502 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -79,7 +79,7 @@ smb_com_query_information_disk(struct smb_request *sr) if ((rc = smb_fsop_statfs(sr->user_cr, sr->tid_tree->t_snode, &df)) != 0) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); unit_size = 1; block_size = df.f_frsize; diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c index 8542a1a1f9..4e5ba4ec88 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb_read.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -75,13 +75,12 @@ smb_com_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -123,7 +122,7 @@ smb_com_lock_and_read(struct smb_request *sr) int rc; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -139,19 +138,18 @@ smb_com_lock_and_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } result = smb_lock_range(sr, sr->fid_ofile, param.r_offset, (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -214,7 +212,7 @@ smb_com_read_raw(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -301,13 +299,12 @@ smb_com_read_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -379,7 +376,7 @@ smb_common_read(struct smb_request *sr, smb_read_param_t *param) if (node->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, node, param->r_offset, - param->r_count, FILE_READ_DATA); + param->r_count, B_FALSE); if (rc != NT_STATUS_SUCCESS) { rc = ERANGE; break; diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c index f22e7187de..0239635663 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rename.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,12 +29,12 @@ #include <sys/synch.h> #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> +#include <sys/nbmlock.h> static int smb_do_rename(struct smb_request *sr, struct smb_fqi *src_fqi, struct smb_fqi *dst_fqi); - /* * smb_com_rename * @@ -63,7 +63,7 @@ smb_com_rename(struct smb_request *sr) int rc; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -99,19 +99,18 @@ smb_com_rename(struct smb_request *sr) * NT and W2K client behaviour. */ if (rc == EEXIST) { - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_COLLISION, + smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERROR_ALREADY_EXISTS); /* NOTREACHED */ } if (rc == EPIPE) { - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ } - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -136,48 +135,6 @@ smb_com_rename(struct smb_request *sr) } /* - * smb_rename_share_check - * - * An open file can be renamed if - * - * 1. isn't opened for data writing or deleting - * - * 2. Opened with "Deny Delete" share mode - * But not opened for data reading or executing - * (opened for accessing meta data) - */ -DWORD -smb_rename_share_check(struct smb_node *node) -{ - struct smb_ofile *open; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - open = smb_llist_head(&node->n_ofile_list); - while (open) { - if (open->f_granted_access & - (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - - if ((open->f_share_access & FILE_SHARE_DELETE) == 0) { - if (open->f_granted_access & - (FILE_READ_DATA | FILE_EXECUTE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - } - open = smb_llist_next(&node->n_ofile_list, open); - } - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SUCCESS); -} - - -/* * smb_do_rename * * Backend to smb_com_rename to ensure that the rename operation is atomic. @@ -228,28 +185,24 @@ smb_do_rename( } } - status = smb_lock_range_access(sr, src_node, 0, 0, FILE_WRITE_DATA); - if (status != NT_STATUS_SUCCESS) { - smb_node_release(src_node); - smb_node_release(src_fqi->dir_snode); + for (count = 0; count <= 3; count++) { + if (count) { + smb_node_end_crit(src_node); + delay(MSEC_TO_TICK(400)); + } - SMB_NULL_FQI_NODES(*src_fqi); - SMB_NULL_FQI_NODES(*dst_fqi); - return (EACCES); - } + smb_node_start_crit(src_node, RW_READER); + status = smb_node_rename_check(src_node); - for (count = 0; count <= 3; count++) { - if (count) - delay(MSEC_TO_TICK(400)); - status = smb_rename_share_check(src_node); if (status != NT_STATUS_SHARING_VIOLATION) break; } - smb_node_release(src_node); - if (status == NT_STATUS_SHARING_VIOLATION) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -257,8 +210,25 @@ smb_do_rename( return (EPIPE); /* = ERRbadshare */ } + status = smb_range_check(sr, sr->user_cr, src_node, 0, UINT64_MAX, + B_TRUE); + + if (status != NT_STATUS_SUCCESS) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); + smb_node_release(src_fqi->dir_snode); + + SMB_NULL_FQI_NODES(*src_fqi); + SMB_NULL_FQI_NODES(*dst_fqi); + return (EACCES); + } + if (utf8_strcasecmp(src_fqi->path, dst_fqi->path) == 0) { if ((rc = smbd_fs_query(sr, dst_fqi, 0)) != 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -276,6 +246,9 @@ smb_do_rename( rc = strcmp(src_fqi->last_comp_od, dst_fqi->last_comp); if (rc == 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); smb_node_release(dst_fqi->dir_snode); @@ -297,11 +270,18 @@ smb_do_rename( SMB_NULL_FQI_NODES(*src_fqi); SMB_NULL_FQI_NODES(*dst_fqi); } + + smb_node_end_crit(src_node); + + smb_node_release(src_node); return (rc); } rc = smbd_fs_query(sr, dst_fqi, FQM_PATH_MUST_NOT_EXIST); if (rc != 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -343,5 +323,9 @@ smb_do_rename( SMB_NULL_FQI_NODES(*dst_fqi); } + smb_node_end_crit(src_node); + + smb_node_release(src_node); + return (rc); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_rpc.c b/usr/src/uts/common/fs/smbsrv/smb_rpc.c index 5059c909b4..a270f442b1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rpc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rpc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -205,7 +205,8 @@ smb_rpc_initialize(struct smb_request *sr, char *pipe_name) op = &sr->arg.open; of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op->desired_access, 0, op->share_access, - SMB_FTYPE_MESG_PIPE, pipe_name, smb_rpc_fid(), &err); + SMB_FTYPE_MESG_PIPE, pipe_name, smb_rpc_fid(), + SMB_UNIQ_FID(), &err); if (of == NULL) return (err.status); @@ -267,7 +268,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) if (pipe_info->fid == 0) { smb_rpc_exit(pipe_info); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); /* NOTREACHED */ } @@ -286,8 +287,8 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) if (rc != 0) { smb_rpc_exit(pipe_info); - smbsr_raise_nt_error(sr, - NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID); + smbsr_error(sr, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID, + 0, 0); /* NOTREACHED */ } @@ -310,13 +311,8 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) xa->rep_data_mb.max_bytes = mdrcnt; MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); - if (sr->session->capabilities & CAP_STATUS32) - smbsr_setup_nt_status(sr, ERROR_SEVERITY_WARNING, - NT_STATUS_BUFFER_OVERFLOW); - else { - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRmoredata; - } + smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, + ERRDOS, ERROR_MORE_DATA); } else { /* * The client has provided enough buffer space, all diff --git a/usr/src/uts/common/fs/smbsrv/smb_sd.c b/usr/src/uts/common/fs/smbsrv/smb_sd.c index fa2bf223d7..c26b70169a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_sd.c +++ b/usr/src/uts/common/fs/smbsrv/smb_sd.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -145,7 +145,7 @@ smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); if (error) { - smb_errmap_unix2smb(error, &smb_err); + smbsr_map_errno(error, &smb_err); return (smb_err.status); } @@ -186,7 +186,7 @@ smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) smb_fssd_term(&fs_sd); if (error) { - smb_errmap_unix2smb(error, &smb_err); + smbsr_map_errno(error, &smb_err); return (smb_err.status); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_search.c b/usr/src/uts/common/fs/smbsrv/smb_search.c index 0700b8fd2d..d0411e1e58 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_search.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -162,7 +162,7 @@ smb_com_search(struct smb_request *sr) } if ((rc = fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -212,8 +212,7 @@ smb_com_search(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -270,13 +269,13 @@ smb_com_search(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ smb_rdir_close(sr); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { smb_rdir_close(sr); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_seek.c b/usr/src/uts/common/fs/smbsrv/smb_seek.c index a120a26a9d..cffb9ce2d0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_seek.c +++ b/usr/src/uts/common/fs/smbsrv/smb_seek.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -94,8 +94,7 @@ smb_com_seek(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -103,27 +102,16 @@ smb_com_seek(struct smb_request *sr) (void) smb_set_file_size(sr); } - rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret); - if (rc == 0) { - smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0); - return (SDRC_NORMAL_REPLY); + if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { + if (rc == EINVAL) { + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + /* NOTREACHED */ + } else { + smbsr_error(sr, 0, ERRSRV, ERRerror); + /* NOTREACHED */ + } } - if (rc == EINVAL) { - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); - /* NOTREACHED */ - } - if (rc == EOVERFLOW) { - smbsr_raise_error(sr, ERRSRV, ERRerror); - /* NOTREACHED */ - } - ASSERT(0); - smbsr_raise_error(sr, ERRSRV, ERRerror); - /* NOTREACHED */ - /* - * Although smbsr_raise_error() doesn't return and the compiler is - * told so in smb_kproto.h it still has a problem if it doesn't - * find here a return instruction with a value. - */ - return (0); + smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c index b7217cf78b..887a0ca648 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -370,7 +370,7 @@ smb_com_session_setup_andx(struct smb_request *sr) kmem_free(ci_password, ci_pwlen + 1); if (cs_password) kmem_free(cs_password, cs_pwlen + 1); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ } else if (utf8_strcasecmp(primary_domain, hostname) == 0) { /* @@ -385,8 +385,6 @@ smb_com_session_setup_andx(struct smb_request *sr) clnt_info.flags |= NETR_CFLG_LOCAL; } - (void) utf8_strupr(primary_domain); - /* * If this is an additional setup for an existing user * on this session, duplicate the authenticated user. @@ -431,7 +429,7 @@ smb_com_session_setup_andx(struct smb_request *sr) kmem_free(ci_password, ci_pwlen + 1); if (cs_password) kmem_free(cs_password, cs_pwlen + 1); - smbsr_raise_error(sr, ERRSRV, ERRbadpw); + smbsr_error(sr, 0, ERRSRV, ERRbadpw); /* NOTREACHED */ } @@ -463,7 +461,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (user == NULL) { if (session_key) kmem_free(session_key, sizeof (smb_session_key_t)); - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_HANDLE); + smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); /* no return */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_set_information.c index 728c86b8cd..e7b1237fa9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,7 +88,7 @@ smb_com_set_information(struct smb_request *sr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -96,7 +96,7 @@ smb_com_set_information(struct smb_request *sr) sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0)) != 0) { smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -118,7 +118,7 @@ smb_com_set_information(struct smb_request *sr) smb_node_release(node); if (rc) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c index 1510f7228a..8f00ff66d1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,16 +77,14 @@ smb_com_set_information2(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } node = sr->fid_ofile->f_node; if (node == 0 || sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { - cmn_err(CE_NOTE, "SmbSetInfo2: access denied"); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -113,7 +111,7 @@ smb_com_set_information2(struct smb_request *sr) smb_node_set_time(node, &crtime, &mtime, &atime, 0, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c index 6ef6691df3..dc85916d04 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -67,8 +67,8 @@ extern int smb_common_create_directory(struct smb_request *sr); int smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa) { - int rc; - DWORD status; + int rc; + DWORD status; if (smb_decode_mbc(&xa->req_param_mb, "%4.s", sr, &sr->arg.dirop.fqi.path) != 0) { @@ -77,16 +77,12 @@ smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa) } if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_NAME); - + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } if ((rc = smb_common_create_directory(sr)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c index c92a248a93..57b3ba257c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -176,36 +176,50 @@ #include <smbsrv/smbtrans.h> #include <smbsrv/smb_fsops.h> -int smb_trans2_find_get_maxdata(struct smb_request *, unsigned short, - unsigned short); +static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t); -int smb_trans2_find_get_dents(struct smb_request *, struct smb_xa *, - unsigned short, unsigned short, int, struct smb_node *, - unsigned short, uint32_t, int, char *, uint32_t *, int *, int *); +int smb_trans2_find_get_dents(smb_request_t *, smb_xa_t *, + uint16_t, uint16_t, int, smb_node_t *, + uint16_t, uint16_t, int, char *, uint32_t *, int *, int *); int smb_gather_dents_info(char *, ino_t, int, char *, uint32_t, int32_t *, - smb_attr_t *, struct smb_node *, char *, char *); + smb_attr_t *, smb_node_t *, char *, char *); -int smb_trans2_find_process_ients(struct smb_request *, struct smb_xa *, - smb_dent_info_hdr_t *, unsigned short, unsigned short, int, - struct smb_node *, int *, uint32_t *); +int smb_trans2_find_process_ients(smb_request_t *, smb_xa_t *, + smb_dent_info_hdr_t *, uint16_t, uint16_t, int, + smb_node_t *, int *, uint32_t *); -int smb_trans2_find_mbc_encode(struct smb_request *, struct smb_xa *, - smb_dent_info_t *, int, unsigned short, unsigned short, - unsigned int, struct smb_node *, struct smb_node *); +int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *, + smb_dent_info_t *, int, uint16_t, uint16_t, + uint32_t, smb_node_t *, smb_node_t *); /* - * Support for Catia Version 5 Deployment + * The UNIX characters below are considered illegal in Windows file names. + * The following character conversions are used to support sites in which + * Catia v4 is in use on UNIX and Catia v5 is in use on Windows. + * + * --------------------------- + * Unix-char | Windows-char + * --------------------------- + * " | (0x00a8) Diaeresis + * * | (0x00a4) Currency Sign + * : | (0x00f7) Division Sign + * < | (0x00ab) Left-Pointing Double Angle Quotation Mark + * > | (0x00bb) Right-Pointing Double Angle Quotation Mark + * ? | (0x00bf) Inverted Question mark + * \ | (0x00ff) Latin Small Letter Y with Diaeresis + * | | (0x00a6) Broken Bar */ -static int (*catia_callback)(unsigned char *, unsigned char *, int) = NULL; +static int (*catia_callback)(uint8_t *, uint8_t *, int) = NULL; void smb_register_catia_callback( - int (*catia_v4tov5)(unsigned char *, unsigned char *, int)); + int (*catia_v4tov5)(uint8_t *, uint8_t *, int)); void smb_unregister_catia_callback(); /* - * Patchable parameter for find maximum count + * Tunable parameter to limit the maximum + * number of entries to be returned. */ -int max_find_count = 64; +uint16_t smb_trans2_find_max = 128; /* * smb_register_catia_callback @@ -216,7 +230,7 @@ int max_find_count = 64; */ void smb_register_catia_callback( - int (*catia_v4tov5)(unsigned char *, unsigned char *, int)) + int (*catia_v4tov5)(uint8_t *, uint8_t *, int)) { catia_callback = catia_v4tov5; } @@ -277,20 +291,21 @@ smb_unregister_catia_callback() * found in the search */ int -smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) +smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) { int more = 0, rc; - unsigned short sattr, fflag, infolev; + uint16_t sattr, fflag, infolev; + uint16_t maxcount = 0; int maxdata; - int count, maxcount = 0, wildcards; + int count, wildcards; uint32_t cookie; char *path; - struct smb_node *dir_snode; + smb_node_t *dir_snode; char *pattern; - unsigned short sid; + uint16_t sid; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -302,27 +317,36 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) } maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); - if (maxdata == 0) { - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, NT_STATUS_INVALID_LEVEL, + ERRDOS, ERROR_INVALID_LEVEL); /* NOTREACHED */ } - /* Convert name to our form */ - if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { + /* + * When maxcount is zero Windows behaves as if it was 1. + */ + if (maxcount == 0) + maxcount = 1; + + if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max)) + maxcount = smb_trans2_find_max; + + if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) (void) smb_convert_unicode_wildcards(path); - } + (void) smb_rdir_open(sr, path, sattr); /* * Get a copy of information */ - pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); dir_snode = sr->sid_odir->d_dir_snode; + pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) strcpy(pattern, sr->sid_odir->d_pattern); - /* this is funky */ + if (strcmp(pattern, "*.*") == 0) (void) strncpy(pattern, "*", sizeof (pattern)); + wildcards = sr->sid_odir->d_wildcards; sattr = sr->sid_odir->d_sattr; cookie = 0; @@ -337,23 +361,22 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) if (rc) { smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } /* - * Save the sid here because search might get closed - * and sr->smb_sid becomes invalid. - * This might not seem important because the search - * is going to be finished anyways, but it's just for - * the sake of compatibility with Windows. + * Save the sid here in case the search is closed below, + * which will invalidate sr->smb_sid. We return the + * sid, even though the search has been closed, to be + * compatible with Windows. */ sid = sr->smb_sid; if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST || - (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) + (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) { smb_rdir_close(sr); - else { + } else { mutex_enter(&sr->sid_odir->d_mutex); sr->sid_odir->d_cookie = cookie; mutex_exit(&sr->sid_odir->d_mutex); @@ -366,8 +389,6 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } - - /* * smb_com_trans2_find_next2 * @@ -418,57 +439,61 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) * matches found in the search */ int -smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) +smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) { - unsigned short fflag, infolev; + uint16_t fflag, infolev; int maxdata, count, wildcards, more = 0, rc; uint32_t cookie; - uint32_t maxcount = 0; - struct smb_node *dir_snode; + uint16_t maxcount = 0; + smb_node_t *dir_snode; char *pattern; - unsigned short sattr; + uint16_t sattr; - pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* - * There is a path field as the last piece of input information: + * The last parameter in the request is a path, which is a + * null-terminated unicode string. * * smb_decode_mbc(&xa->req_param_mb, "%www lwu", sr, - * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &path) + * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &path) * - * This feild has been removed because it's causing problem - * with Mac OS 10 and it's not used anyways. - * The problem is that code expects to see a 2-byte null - * because the strings are supposed to be Unicode, but - * Max OS 10 sends a 1-byte null which leads to decode error. + * We don't reference this parameter and it is not currently + * decoded because we a expect 2-byte null but Mac OS 10 + * clients send a 1-byte null, which leads to a decode error. */ if (smb_decode_mbc(&xa->req_param_mb, "%www lw", sr, &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag) != 0) { - kmem_free(pattern, MAXNAMELEN); smbsr_decode_error(sr); /* NOTREACHED */ } - maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); - sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - kmem_free(pattern, MAXNAMELEN); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } + maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); if (maxdata == 0) { smb_rdir_close(sr); - kmem_free(pattern, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, NT_STATUS_INVALID_LEVEL, + ERRDOS, ERROR_INVALID_LEVEL); /* NOTREACHED */ } /* + * When maxcount is zero Windows behaves as if it was 1. + */ + if (maxcount == 0) + maxcount = 1; + + if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max)) + maxcount = smb_trans2_find_max; + + /* * Get a copy of information */ dir_snode = sr->sid_odir->d_dir_snode; + pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) strcpy(pattern, sr->sid_odir->d_pattern); wildcards = sr->sid_odir->d_wildcards; sattr = sr->sid_odir->d_sattr; @@ -478,17 +503,6 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) mutex_exit(&sr->sid_odir->d_mutex); } - /* - * XXX this is an optimization made for SFS2 filesystem, it might - * not be required for ZFS - * - * Break the count to smaller counts (less than the default 150) - * to reduce the number of transaction failures - * which may cause excessive delays and eventually a SMB staled - * connection. - */ - maxcount = (maxcount > max_find_count) ? max_find_count : maxcount; - rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata, dir_snode, sattr, maxcount, wildcards, pattern, &cookie, &more, &count); @@ -496,7 +510,7 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) if (rc) { smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -516,21 +530,17 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } - /* * smb_trans2_find_get_maxdata * - * This function calculates the minimum space requirement for the - * base on information level and fflag. + * Calculate the minimum response space required for the specified + * information level. * - * When success, minimum space requirement will be returned; otherwise, - * 0 will be returned. + * A non-zero return value provides the minimum space required. + * A return value of zero indicates an unknown information level. */ -int -smb_trans2_find_get_maxdata( - struct smb_request *sr, - unsigned short infolev, - unsigned short fflag) +static int +smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag) { int maxdata; @@ -573,8 +583,6 @@ smb_trans2_find_get_maxdata( return (maxdata); } - - /* * smb_trans2_find_get_dents * @@ -591,12 +599,12 @@ smb_trans2_find_get_maxdata( int smb_trans2_find_get_dents( smb_request_t *sr, smb_xa_t *xa, - unsigned short fflag, - unsigned short infolev, + uint16_t fflag, + uint16_t infolev, int maxdata, smb_node_t *dir_snode, - unsigned short sattr, - uint32_t maxcount, + uint16_t sattr, + uint16_t maxcount, int wildcards, char *pattern, uint32_t *cookie, @@ -686,7 +694,7 @@ int smb_get_dents( smb_request_t *sr, uint32_t *cookie, smb_node_t *dir_snode, - unsigned int wildcards, + uint32_t wildcards, smb_dent_info_hdr_t *ihdr, int *more) { @@ -787,8 +795,8 @@ smb_gather_dents_info( /*LINTED E_BAD_PTR_CAST_ALIGN*/ smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)args; smb_dent_info_t *ient; - unsigned char *v5_name = NULL; - unsigned char *np = (unsigned char *)name; + uint8_t *v5_name = NULL; + uint8_t *np = (uint8_t *)name; int reclen = sizeof (smb_dent_info_t) + namelen; v5_name = kmem_alloc(MAXNAMELEN-1, KM_SLEEP); @@ -805,28 +813,8 @@ smb_gather_dents_info( return (0); } - /* - * If StorEdge is configured to support Catia Version 5 deployments, - * any directory entry whose name contains the special Unix character - * that is considered to be illegal in Windows environement will be - * translated based on the following - * Special Character Translation Table. - * - * --------------------------- - * Unix-char | Windows-char - * --------------------------- - * " | (0x00a8) Diaeresis - * * | (0x00a4) Currency Sign - * : | (0x00f7) Division Sign - * < | (0x00ab) Left-Pointing Double Angle Quotation Mark - * > | (0x00bb) Right-Pointing Double Angle Quotation Mark - * ? | (0x00bf) Inverted Question mark - * \ | (0x00ff) Latin Small Letter Y with Diaeresis - * | | (0x00a6) Broken Bar - */ if (catia_callback) { - /* XXX 255 should be max name len or something */ - catia_callback(v5_name, (unsigned char *)name, 255); + catia_callback(v5_name, (uint8_t *)name, MAXNAMELEN-1); np = v5_name; reclen = sizeof (smb_dent_info_t) + strlen((char *)v5_name); } @@ -876,15 +864,15 @@ smb_gather_dents_info( */ int smb_trans2_find_process_ients( - struct smb_request *sr, - struct smb_xa *xa, - smb_dent_info_hdr_t *ihdr, - unsigned short fflag, - unsigned short infolev, - int maxdata, - struct smb_node *dir_snode, - int *more, - uint32_t *cookie) + smb_request_t *sr, + smb_xa_t *xa, + smb_dent_info_hdr_t *ihdr, + uint16_t fflag, + uint16_t infolev, + int maxdata, + smb_node_t *dir_snode, + int *more, + uint32_t *cookie) { int i, err = 0; smb_dent_info_t *ient; @@ -897,15 +885,15 @@ smb_trans2_find_process_ients( break; /* - * FYI: Some observed differences between our response and - * Windows response which hasn't caused problem yet! + * Observed differences between our response and Windows + * response, which hasn't caused a problem yet! * - * 1. The NextEntryOffset field for the last entry should be 0 - * This code always calculate the record length and put the - * result in this field. + * 1. The NextEntryOffset field for the last entry should + * be 0. This code always calculate the record length + * and puts the result in the NextEntryOffset field. * - * 2. The FileIndex field is always 0. This code put the cookie - * in this field. + * 2. The FileIndex field is always 0. This code puts + * the cookie in the FileIndex field. */ err = smb_trans2_find_mbc_encode(sr, xa, ient, maxdata, infolev, fflag, mb_flags, dir_snode, NULL); @@ -915,8 +903,8 @@ smb_trans2_find_process_ients( } /* - * Not enough space to store all the entries returned; therefore, - * update the more to 1. + * Not enough space to store all the entries returned, + * which is indicated by setting more. */ if (more && err < 0) { *more = 1; @@ -931,8 +919,6 @@ smb_trans2_find_process_ients( return (i); } - - /* * smb_trans2_find_mbc_encode * @@ -942,45 +928,45 @@ smb_trans2_find_process_ients( * is reached. If the entry is valid and successful encoded, 0 * will be returned; otherwise, 1 will be returned. */ -int smb_trans2_find_mbc_encode( - struct smb_request *sr, - struct smb_xa *xa, - smb_dent_info_t *ient, - int maxdata, - unsigned short infolev, - unsigned short fflag, - unsigned int mb_flags, - struct smb_node *dir_snode, /*LINTED E_FUNC_ARG_UNUSED*/ - struct smb_node *sd_snode) +int /*ARGSUSED*/ +smb_trans2_find_mbc_encode( + smb_request_t *sr, + smb_xa_t *xa, + smb_dent_info_t *ient, + int maxdata, + uint16_t infolev, + uint16_t fflag, + uint32_t mb_flags, + smb_node_t *dir_snode, + smb_node_t *sd_snode) { int uni_namelen; - int sl, rl; + int shortlen; + uint32_t next_entry_offset; char buf83[26]; smb_msgbuf_t mb; uint32_t dattr = 0; uint32_t size32 = 0; uint64_t size64 = 0; - struct smb_node *lnk_snode; + smb_node_t *lnk_snode; smb_attr_t lnkattr; int rc; uni_namelen = smb_ascii_or_unicode_strlen(sr, ient->name); - if (uni_namelen == -1) return (1); + next_entry_offset = maxdata + uni_namelen; + if (MBC_ROOM_FOR(&xa->rep_data_mb, (maxdata + uni_namelen)) == 0) return (-1); if (ient->attr.sa_vattr.va_type == VLNK) { - rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, sr->tid_tree->t_snode, dir_snode, ient->name, &lnk_snode, &lnkattr, 0, 0); /* - * IR 104598 - * * We normally want to resolve the object to which a symlink * refers so that CIFS clients can access sub-directories and * find the correct association for files. This causes a @@ -990,7 +976,7 @@ int smb_trans2_find_mbc_encode( * Some Windows applications (i.e. virus scanning) loop/hang * trying to follow this recursive path and there is little * we can do because the path is constructed on the client. - * So we've added a flag that allows an end-user to disable + * skc_dirsymlink_enable allows an end-user to disable * symlinks to directories. Symlinks to other object types * should be unaffected. */ @@ -1012,10 +998,6 @@ int smb_trans2_find_mbc_encode( dattr = smb_mode_to_dos_attributes(&ient->attr); } - /* - * we don't send the '.stream' to client. User shouldn't - * see this directory. - */ switch (infolev) { case SMB_INFO_STANDARD: if (fflag & SMB_FIND_RETURN_RESUME_KEYS) @@ -1036,8 +1018,8 @@ int smb_trans2_find_mbc_encode( case SMB_INFO_QUERY_EA_SIZE: if (fflag & SMB_FIND_RETURN_RESUME_KEYS) - (void) smb_encode_mbc(&xa->rep_data_mb, - "l", ient->cookie); + (void) smb_encode_mbc(&xa->rep_data_mb, "l", + ient->cookie); (void) smb_encode_mbc(&xa->rep_data_mb, "%yyyllwlbu", sr, ient->attr.sa_crtime.tv_sec ? ient->attr.sa_crtime.tv_sec : @@ -1053,11 +1035,8 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_DIRECTORY_INFO: - /* Use maxdata instead */ - rl = maxdata + uni_namelen; - (void) smb_encode_mbc(&xa->rep_data_mb, "%llTTTTqqllu", sr, - rl, + next_entry_offset, ient->cookie, ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime : &ient->attr.sa_vattr.va_mtime, @@ -1072,20 +1051,18 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - /* Use maxdata instead */ - rl = maxdata + uni_namelen; bzero(buf83, sizeof (buf83)); - smb_msgbuf_init(&mb, (unsigned char *)buf83, sizeof (buf83), + smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83), mb_flags); if (smb_msgbuf_encode(&mb, "u", ient->shortname) < 0) { smb_msgbuf_term(&mb); return (-1); } - sl = smb_ascii_or_unicode_strlen(sr, ient->shortname); + shortlen = smb_ascii_or_unicode_strlen(sr, ient->shortname); - (void) smb_encode_mbc(&xa->rep_data_mb, - "%llTTTTqqlllb.24cu", sr, - rl, + (void) smb_encode_mbc(&xa->rep_data_mb, "%llTTTTqqlllb.24cu", + sr, + next_entry_offset, ient->cookie, ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime : &ient->attr.sa_vattr.va_mtime, @@ -1097,7 +1074,7 @@ int smb_trans2_find_mbc_encode( dattr, uni_namelen, 0L, - sl, + shortlen, buf83, ient->name); @@ -1105,9 +1082,8 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_NAMES_INFO: - rl = maxdata + uni_namelen; (void) smb_encode_mbc(&xa->rep_data_mb, "%lllu", sr, - rl, + next_entry_offset, ient->cookie, uni_namelen, ient->name); @@ -1121,7 +1097,7 @@ int smb_trans2_find_mbc_encode( * Close a search started by a Trans2FindFirst2 request. */ int -smb_com_find_close2(struct smb_request *sr) +smb_com_find_close2(smb_request_t *sr) { if (smbsr_decode_vwv(sr, "w", &sr->smb_sid) != 0) { smbsr_decode_error(sr); @@ -1130,13 +1106,11 @@ smb_com_find_close2(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } smb_rdir_close(sr); - smbsr_encode_empty_result(sr); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c index e6d4dbeccf..d4b5443cd9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -105,8 +105,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -176,7 +175,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) break; default: - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOTREACHED */ break; } @@ -359,7 +358,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) if (dir_snode == NULL) { kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOT REACHED */ } (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); @@ -386,7 +385,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) default: kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c index 509c4094f0..a1820b899e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -283,14 +283,14 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) snode = sr->tid_tree->t_snode; if (fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr) != 0) { - smbsr_raise_errno(sr, ESTALE); + smbsr_errno(sr, ESTALE); /* NOTREACHED */ } switch (infolev) { case SMB_INFO_ALLOCATION: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -365,7 +365,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) case SMB_QUERY_FS_SIZE_INFO: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -425,7 +425,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) break; default: - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c index 374a6de2bd..bea67e6545 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -341,7 +341,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) int len; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -382,7 +382,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -393,7 +393,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } smb_node_release(dir_node); @@ -576,7 +576,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c index 094032da1c..de71abb6d3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -123,7 +123,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || SMB_TREE_IS_READ_ONLY(sr)) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -131,8 +131,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -142,7 +141,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) !SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { cmn_err(CE_NOTE, "SmbT2SetFileInfo: access denied"); kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -154,8 +153,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } else if (status == NT_STATUS_UNSUCCESSFUL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, smberr.status, - smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ } kmem_free(info, sizeof (smb_trans2_setinfo_t)); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c index 8c4368f93f..782e42f36d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -228,7 +228,7 @@ smb_set_standard_info( smb_node_set_time(node, &crtime, &mtime, &atime, 0, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } @@ -295,7 +295,7 @@ smb_set_basic_info( smb_node_set_time(node, &crtime, &mtime, &atime, &ctime, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } @@ -339,7 +339,7 @@ smb_set_alloc_info( * write requests without the inode ever being updated. */ if ((rc = smb_set_file_size(sr)) != 0) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c index 02be8c53cb..fd3c2d571f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -134,7 +134,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || SMB_TREE_IS_READ_ONLY(sr)) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -145,7 +145,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -157,7 +157,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); } info->node = ret_snode; @@ -170,8 +170,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } else if (status == NT_STATUS_UNSUCCESSFUL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, smberr.status, - smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ } kmem_free(info, sizeof (smb_trans2_setinfo_t)); diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c index 9139930a4d..560c1d7b76 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -100,9 +100,10 @@ smb_com_tree_disconnect(struct smb_request *sr) sr->smb_tid); if (sr->uid_user == NULL || sr->tid_tree == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRinvnid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid); + /* NOTREACHED */ } + smbsr_rq_notify(sr, sr->session, sr->tid_tree); smb_tree_disconnect(sr->tid_tree); smbsr_encode_empty_result(sr); diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c index fef432d9fc..8e75fadc36 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,15 +69,15 @@ smb_com_unlock_byte_range(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, (u_offset_t)Offset, (uint64_t)Length); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c index 538c9cfc91..0e9bbe45f2 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_vops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,9 @@ #include <sys/pathname.h> #include <sys/cred.h> #include <sys/extdirent.h> +#include <sys/nbmlock.h> +#include <sys/share.h> +#include <sys/fcntl.h> #include <smbsrv/smb_vops.h> #include <smbsrv/string.h> @@ -43,21 +46,22 @@ #include <smbsrv/smb_kproto.h> #include <smbsrv/smb_incl.h> +void +smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr); static int smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, - cred_t *cr, caller_context_t *ct, int flags); + cred_t *cr, int flags); static int smb_vop_readdir_entry(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr, - caller_context_t *ct, char *dirbuf, int num_bytes); + char *dirbuf, int num_bytes); static int smb_vop_getdents_entries(smb_node_t *dir_snode, uint32_t *cookiep, int32_t *dircountp, char *arg, uint32_t flags, struct smb_request *sr, - cred_t *cr, caller_context_t *ct, char *dirbuf, int *maxentries, - int num_bytes, char *); + cred_t *cr, char *dirbuf, int *maxentries, int num_bytes, char *); extern int smb_gather_dents_info(char *args, ino_t fileid, int namelen, @@ -68,6 +72,8 @@ smb_gather_dents_info(char *args, ino_t fileid, int namelen, static void smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp); +extern sysid_t lm_alloc_sysidt(); + #define SMB_AT_MAX 16 static uint_t smb_attrmap[SMB_AT_MAX] = { 0, @@ -88,16 +94,45 @@ static uint_t smb_attrmap[SMB_AT_MAX] = { AT_SEQ }; +/* + * The smb_ct will be used primarily for range locking. + * Since the CIFS server is mapping its locks to POSIX locks, + * only one pid is used for operations originating from the + * CIFS server (to represent CIFS in the VOP_FRLOCK routines). + */ + +caller_context_t smb_ct; + +/* + * smb_vop_start() + * + * Initialize the smb caller context. This function must be called + * before any other smb_vop calls. + */ + +void +smb_vop_start(void) +{ + static boolean_t initialized = B_FALSE; + + if (!initialized) { + smb_ct.cc_caller_id = fs_new_caller_id(); + smb_ct.cc_pid = ttoproc(curthread)->p_pid; + smb_ct.cc_sysid = lm_alloc_sysidt(); + initialized = B_TRUE; + } +} + int -smb_vop_open(vnode_t **vpp, int mode, cred_t *cred, caller_context_t *ct) +smb_vop_open(vnode_t **vpp, int mode, cred_t *cred) { - return (VOP_OPEN(vpp, mode, cred, ct)); + return (VOP_OPEN(vpp, mode, cred, &smb_ct)); } int -smb_vop_close(vnode_t *vp, int mode, cred_t *cred, caller_context_t *ct) +smb_vop_close(vnode_t *vp, int mode, cred_t *cred) { - return (VOP_CLOSE(vp, mode, 1, (offset_t)0, cred, ct)); + return (VOP_CLOSE(vp, mode, 1, (offset_t)0, cred, &smb_ct)); } /* @@ -115,19 +150,19 @@ smb_vop_close(vnode_t *vp, int mode, cred_t *cred, caller_context_t *ct) */ int -smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct) +smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr) { int error; (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); - error = VOP_READ(vp, uiop, 0, cr, ct); + error = VOP_READ(vp, uiop, 0, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); return (error); } int smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; int ioflag = 0; @@ -140,7 +175,7 @@ smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, uiop->uio_llimit = MAXOFFSET_T; (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); - error = VOP_WRITE(vp, uiop, ioflag, cr, ct); + error = VOP_WRITE(vp, uiop, ioflag, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); *lcount -= uiop->uio_resid; @@ -168,7 +203,7 @@ smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, - int flags, cred_t *cr, caller_context_t *ct) + int flags, cred_t *cr) { int error; vnode_t *use_vp; @@ -197,7 +232,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); if ((error = VOP_GETATTR(use_vp, (vattr_t *)&tmp_xvattr, flags, - cr, ct)) != 0) + cr, &smb_ct)) != 0) return (error); ret_attr->sa_vattr = tmp_xvattr.xva_vattr; @@ -250,7 +285,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, tmp_xvattr.xva_vattr.va_mask = AT_SIZE; if ((error = VOP_GETATTR(vp, (vattr_t *)&tmp_xvattr, - flags, cr, ct)) != 0) + flags, cr, &smb_ct)) != 0) return (error); ret_attr->sa_vattr.va_size = @@ -272,7 +307,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, smb_sa_to_va_mask(ret_attr->sa_mask, &ret_attr->sa_vattr.va_mask); - error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, ct); + error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); @@ -297,7 +332,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, */ tmp_attr.sa_vattr.va_mask = AT_SIZE; - error = VOP_GETATTR(vp, &tmp_attr.sa_vattr, flags, cr, ct); + error = VOP_GETATTR(vp, &tmp_attr.sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); @@ -326,14 +361,13 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, - int flags, cred_t *cr, boolean_t no_xvattr, caller_context_t *ct) + int flags, cred_t *cr, boolean_t no_xvattr) { int error = 0; int at_size = 0; vnode_t *use_vp; - xvattr_t tmp_xvattr; - xoptattr_t *xoap = NULL; - uint_t xva_mask; + xvattr_t xvattr; + vattr_t *vap; if (unnamed_vp) { use_vp = unnamed_vp; @@ -354,116 +388,24 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, if ((no_xvattr == B_FALSE) && vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { - /* - * Initialize xvattr, including bzero - */ - xva_init(&tmp_xvattr); - xoap = xva_getxoptattr(&tmp_xvattr); - - ASSERT(xoap); - - /* - * Copy caller-specified classic attributes to tmp_xvattr. - * First save tmp_xvattr's mask (set in xva_init()), which - * contains AT_XVATTR. This is |'d in later if needed. - */ - - xva_mask = tmp_xvattr.xva_vattr.va_mask; - tmp_xvattr.xva_vattr = set_attr->sa_vattr; + smb_vop_setup_xvattr(set_attr, &xvattr); + vap = (vattr_t *)&xvattr; + } else { smb_sa_to_va_mask(set_attr->sa_mask, - &tmp_xvattr.xva_vattr.va_mask); - - /* - * Do not set ctime (only the file system can do it) - */ - - tmp_xvattr.xva_vattr.va_mask &= ~AT_CTIME; - - if (set_attr->sa_mask & SMB_AT_DOSATTR) { - - /* - * "|" in the original xva_mask, which contains - * AT_XVATTR - */ - - tmp_xvattr.xva_vattr.va_mask |= xva_mask; - - XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE); - XVA_SET_REQ(&tmp_xvattr, XAT_SYSTEM); - XVA_SET_REQ(&tmp_xvattr, XAT_READONLY); - XVA_SET_REQ(&tmp_xvattr, XAT_HIDDEN); - - /* - * set_attr->sa_dosattr: If a given bit is not set, - * that indicates that the corresponding field needs - * to be updated with a "0" value. This is done - * implicitly as the xoap->xoa_* fields were bzero'd. - */ - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_ARCHIVE) - xoap->xoa_archive = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_SYSTEM) - xoap->xoa_system = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_READONLY) - xoap->xoa_readonly = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) - xoap->xoa_hidden = 1; - } - - if (set_attr->sa_mask & SMB_AT_CRTIME) { - /* - * "|" in the original xva_mask, which contains - * AT_XVATTR - */ - - tmp_xvattr.xva_vattr.va_mask |= xva_mask; - XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); - xoap->xoa_createtime = set_attr->sa_crtime; - } - - if ((error = VOP_SETATTR(use_vp, (vattr_t *)&tmp_xvattr, flags, - cr, ct)) != 0) - return (error); - - /* - * If the size of the stream needs to be set, set it on - * the stream file directly. (All other indicated attributes - * are set on the stream's unnamed stream, above.) - */ - - if (at_size) { - /* - * set_attr->sa_vattr.va_size already contains the - * size as set by the caller - * - * Note that vp is used here, and not use_vp. - * Also, only AT_SIZE is needed. - */ + &set_attr->sa_vattr.va_mask); + vap = &set_attr->sa_vattr; + } - set_attr->sa_vattr.va_mask = AT_SIZE; - error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, - cr, ct); - } + if ((error = VOP_SETATTR(use_vp, vap, flags, cr, &smb_ct)) != 0) return (error); - } - /* - * Support for file systems without VFSFT_XVATTR or no_xvattr == B_TRUE - */ - smb_sa_to_va_mask(set_attr->sa_mask, &set_attr->sa_vattr.va_mask); + /* - * set_attr->sa_vattr already contains new values - * as set by the caller + * If the size of the stream needs to be set, set it on + * the stream file directly. (All other indicated attributes + * are set on the stream's unnamed stream, above.) */ - error = VOP_SETATTR(use_vp, &set_attr->sa_vattr, flags, cr, ct); - - if (error != 0) - return (error); - if (at_size) { /* * set_attr->sa_vattr.va_size already contains the @@ -474,8 +416,10 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, */ set_attr->sa_vattr.va_mask = AT_SIZE; - error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, ct); + error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, + &smb_ct); } + return (error); } @@ -531,7 +475,7 @@ smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, cred_t *cr) int smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, - int flags, vnode_t *rootvp, cred_t *cr, caller_context_t *ct) + int flags, vnode_t *rootvp, cred_t *cr) { int error = 0; int option_flags = 0; @@ -578,7 +522,7 @@ smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, pn_alloc(&rpn); error = VOP_LOOKUP(dvp, name, vpp, NULL, option_flags, NULL, cr, - ct, NULL, &rpn); + &smb_ct, NULL, &rpn); if ((error == 0) && od_name) { bzero(od_name, MAXNAMELEN); @@ -594,25 +538,34 @@ smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, int smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, - int flags, cred_t *cr, caller_context_t *ct, vsecattr_t *vsap) + int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; + xvattr_t xvattr; + vattr_t *vap; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; - smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); + attr->sa_vattr.va_mask = 0; + + if (vfs_has_feature(dvp->v_vfsp, VFSFT_XVATTR)) { + smb_vop_setup_xvattr(attr, &xvattr); + vap = (vattr_t *)&xvattr; + } else { + smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); + vap = &attr->sa_vattr; + } - error = VOP_CREATE(dvp, name, &attr->sa_vattr, EXCL, - attr->sa_vattr.va_mode, vpp, cr, option_flags, ct, vsap); + error = VOP_CREATE(dvp, name, vap, EXCL, attr->sa_vattr.va_mode, + vpp, cr, option_flags, &smb_ct, vsap); return (error); } int -smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -620,7 +573,7 @@ smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; - error = VOP_REMOVE(dvp, name, cr, ct, option_flags); + error = VOP_REMOVE(dvp, name, cr, &smb_ct, option_flags); return (error); } @@ -633,7 +586,7 @@ smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, - char *to_name, int flags, cred_t *cr, caller_context_t *ct) + char *to_name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -643,14 +596,14 @@ smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, option_flags = FIGNORECASE; error = VOP_RENAME(from_dvp, from_name, to_dvp, to_name, cr, - ct, option_flags); + &smb_ct, option_flags); return (error); } int smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, - int flags, cred_t *cr, caller_context_t *ct, vsecattr_t *vsap) + int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; @@ -662,7 +615,7 @@ smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); - error = VOP_MKDIR(dvp, name, &attr->sa_vattr, vpp, cr, ct, + error = VOP_MKDIR(dvp, name, &attr->sa_vattr, vpp, cr, &smb_ct, option_flags, vsap); return (error); @@ -677,8 +630,7 @@ smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, */ int -smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -698,16 +650,94 @@ smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, * remove. */ - error = VOP_RMDIR(dvp, name, rootdir, cr, ct, option_flags); + error = VOP_RMDIR(dvp, name, rootdir, cr, &smb_ct, option_flags); return (error); } int -smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct) +smb_vop_commit(vnode_t *vp, cred_t *cr) +{ + return (VOP_FSYNC(vp, 1, cr, &smb_ct)); +} + +void +smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr) { - return (VOP_FSYNC(vp, 1, cr, ct)); + xoptattr_t *xoap = NULL; + uint_t xva_mask; + + /* + * Initialize xvattr, including bzero + */ + xva_init(xvattr); + xoap = xva_getxoptattr(xvattr); + + ASSERT(xoap); + + /* + * Copy caller-specified classic attributes to xvattr. + * First save xvattr's mask (set in xva_init()), which + * contains AT_XVATTR. This is |'d in later if needed. + */ + + xva_mask = xvattr->xva_vattr.va_mask; + xvattr->xva_vattr = smb_attr->sa_vattr; + + smb_sa_to_va_mask(smb_attr->sa_mask, &xvattr->xva_vattr.va_mask); + + /* + * Do not set ctime (only the file system can do it) + */ + + xvattr->xva_vattr.va_mask &= ~AT_CTIME; + + if (smb_attr->sa_mask & SMB_AT_DOSATTR) { + + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + xvattr->xva_vattr.va_mask |= xva_mask; + + XVA_SET_REQ(xvattr, XAT_ARCHIVE); + XVA_SET_REQ(xvattr, XAT_SYSTEM); + XVA_SET_REQ(xvattr, XAT_READONLY); + XVA_SET_REQ(xvattr, XAT_HIDDEN); + + /* + * smb_attr->sa_dosattr: If a given bit is not set, + * that indicates that the corresponding field needs + * to be updated with a "0" value. This is done + * implicitly as the xoap->xoa_* fields were bzero'd. + */ + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_ARCHIVE) + xoap->xoa_archive = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_SYSTEM) + xoap->xoa_system = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_READONLY) + xoap->xoa_readonly = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) + xoap->xoa_hidden = 1; + } + + if (smb_attr->sa_mask & SMB_AT_CRTIME) { + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + xvattr->xva_vattr.va_mask |= xva_mask; + XVA_SET_REQ(xvattr, XAT_CREATETIME); + xoap->xoa_createtime = smb_attr->sa_crtime; + } } + /* * smb_vop_readdir() * @@ -724,8 +754,7 @@ smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct) int smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, - ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr, - caller_context_t *ct) + ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr) { int num_bytes; int error = 0; @@ -737,7 +766,6 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, ASSERT(namelen); ASSERT(inop); ASSERT(cr); - ASSERT(ct); if (dvp->v_type != VDIR) { *namelen = 0; @@ -759,7 +787,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, */ while ((error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep, - &num_bytes, cr, ct, flags)) == 0) { + &num_bytes, cr, flags)) == 0) { if (num_bytes <= 0) break; @@ -767,7 +795,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, name[0] = '\0'; error = smb_vop_readdir_entry(dvp, cookiep, name, namelen, - inop, vpp, od_name, flags, cr, ct, dirbuf, + inop, vpp, od_name, flags, cr, dirbuf, num_bytes); if (error) @@ -815,7 +843,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, static int smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, - cred_t *cr, caller_context_t *ct, int flags) + cred_t *cr, int flags) { int error = 0; int rdirent_flags = 0; @@ -856,7 +884,7 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, auio.uio_fmode = 0; (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); - error = VOP_READDIR(vp, &auio, cr, &sink, ct, rdirent_flags); + error = VOP_READDIR(vp, &auio, cr, &sink, &smb_ct, rdirent_flags); VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); if (error) { @@ -900,7 +928,7 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, static int smb_vop_readdir_entry(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr, - caller_context_t *ct, char *dirbuf, int num_bytes) + char *dirbuf, int num_bytes) { uint32_t next_cookie; int ebufsize; @@ -969,7 +997,7 @@ smb_vop_readdir_entry(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, */ error = smb_vop_lookup(dvp, edp->ed_name, vpp ? vpp : &vp, - od_name, 0, NULL, cr, ct); + od_name, 0, NULL, cr); if (error) { if (error == ENOENT) { @@ -1080,8 +1108,7 @@ smb_vop_getdents( char *pattern, uint32_t flags, smb_request_t *sr, - cred_t *cr, - caller_context_t *ct) + cred_t *cr) { int error = 0; int maxentries; @@ -1107,13 +1134,13 @@ smb_vop_getdents( num_bytes = SMB_MINLEN_RDDIR_BUF; error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep, - &num_bytes, cr, ct, flags); + &num_bytes, cr, flags); if (error || (num_bytes <= 0)) break; error = smb_vop_getdents_entries(dir_snode, cookiep, dircountp, - arg, flags, sr, cr, ct, dirbuf, &maxentries, num_bytes, + arg, flags, sr, cr, dirbuf, &maxentries, num_bytes, pattern); if (error) @@ -1158,7 +1185,6 @@ smb_vop_getdents_entries( uint32_t flags, struct smb_request *sr, cred_t *cr, - caller_context_t *ct, char *dirbuf, int *maxentries, int num_bytes, @@ -1219,7 +1245,7 @@ smb_vop_getdents_entries( } error = smb_vop_lookup(dvp, edp->ed_name, &fvp, - NULL, 0, NULL, cr, ct); + NULL, 0, NULL, cr); if (error) { if (error == ENOENT) { @@ -1335,14 +1361,14 @@ smb_vop_getdents_entries( int smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, char *od_name, vnode_t **xattrdirvpp, int flags, vnode_t *rootvp, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { char *solaris_stream_name; char *name; int error; if ((error = smb_vop_lookup_xattrdir(fvp, xattrdirvpp, - LOOKUP_XATTR | CREATE_XATTR_DIR, cr, ct)) != 0) + LOOKUP_XATTR | CREATE_XATTR_DIR, cr)) != 0) return (error); /* @@ -1361,7 +1387,7 @@ smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, name = kmem_zalloc(MAXNAMELEN, KM_SLEEP); if ((error = smb_vop_lookup(*xattrdirvpp, solaris_stream_name, vpp, - name, flags, rootvp, cr, ct)) != 0) { + name, flags, rootvp, cr)) != 0) { VN_RELE(*xattrdirvpp); } else { (void) strlcpy(od_name, &(name[SMB_STREAM_PREFIX_LEN]), @@ -1376,14 +1402,13 @@ smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, int smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, - vnode_t **vpp, vnode_t **xattrdirvpp, int flags, cred_t *cr, - caller_context_t *ct) + vnode_t **vpp, vnode_t **xattrdirvpp, int flags, cred_t *cr) { char *solaris_stream_name; int error; if ((error = smb_vop_lookup_xattrdir(fvp, xattrdirvpp, - LOOKUP_XATTR | CREATE_XATTR_DIR, cr, ct)) != 0) + LOOKUP_XATTR | CREATE_XATTR_DIR, cr)) != 0) return (error); /* @@ -1395,7 +1420,7 @@ smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, stream_name); if ((error = smb_vop_create(*xattrdirvpp, solaris_stream_name, attr, - vpp, flags, cr, ct, NULL)) != 0) + vpp, flags, cr, NULL)) != 0) VN_RELE(*xattrdirvpp); kmem_free(solaris_stream_name, MAXNAMELEN); @@ -1404,15 +1429,14 @@ smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, } int -smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr) { char *solaris_stream_name; vnode_t *xattrdirvp; int error; - if ((error = smb_vop_lookup_xattrdir(vp, &xattrdirvp, LOOKUP_XATTR, cr, - ct)) != 0) + if ((error = smb_vop_lookup_xattrdir(vp, &xattrdirvp, LOOKUP_XATTR, cr)) + != 0) return (error); /* @@ -1424,7 +1448,7 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, stream_name); /* XXX might have to use kcred */ - error = smb_vop_remove(xattrdirvp, solaris_stream_name, flags, cr, ct); + error = smb_vop_remove(xattrdirvp, solaris_stream_name, flags, cr); kmem_free(solaris_stream_name, MAXNAMELEN); @@ -1444,7 +1468,7 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, int smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, struct fs_stream_info *stream_info, vnode_t **vpp, vnode_t **xattrdirvpp, - int flags, cred_t *cr, caller_context_t *ct) + int flags, cred_t *cr) { int nsize = MAXNAMELEN-1; int error = 0; @@ -1454,7 +1478,7 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, vnode_t *vp; if ((error = smb_vop_lookup_xattrdir(fvp, &xattrdirvp, LOOKUP_XATTR, - cr, ct)) != 0) + cr)) != 0) return (error); bzero(stream_info->name, sizeof (stream_info->name)); @@ -1464,7 +1488,7 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, for (;;) { error = smb_vop_readdir(xattrdirvp, cookiep, tmp_name, &nsize, - &ino, &vp, NULL, flags | SMB_STREAM_RDDIR, cr, ct); + &ino, &vp, NULL, flags | SMB_STREAM_RDDIR, cr); if (error || (*cookiep == SMB_EOF)) break; @@ -1504,12 +1528,12 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, int smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, int flags, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; - error = VOP_LOOKUP(fvp, "", xattrdirvpp, NULL, flags, NULL, cr, ct, - NULL, NULL); + error = VOP_LOOKUP(fvp, "", xattrdirvpp, NULL, flags, NULL, cr, + &smb_ct, NULL, NULL); return (error); } @@ -1560,7 +1584,7 @@ smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr) */ int smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; vsecattr_t vsecattr; @@ -1585,7 +1609,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, return (EINVAL); } - if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, ct)) + if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct)) return (error); *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type); @@ -1601,8 +1625,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, * Writes the given ACL in aclp for the specified file. */ int -smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr) { int error; vsecattr_t vsecattr; @@ -1615,7 +1638,7 @@ smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, if (error == 0) { (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); - error = VOP_SETSECATTR(vp, &vsecattr, flags, cr, ct); + error = VOP_SETSECATTR(vp, &vsecattr, flags, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); } @@ -1713,3 +1736,93 @@ smb_vop_eaccess(vnode_t *vp, int *mode, int flags, vnode_t *dir_vp, cred_t *cr) } } } + +/* + * smb_vop_shrlock() + * + * See comments for smb_fsop_shrlock() + */ + +int +smb_vop_shrlock(vnode_t *vp, uint32_t uniq_fid, uint32_t desired_access, + uint32_t share_access, cred_t *cr) +{ + struct shrlock shr; + struct shr_locowner shr_own; + short new_access = 0; + short deny = 0; + int flag = 0; + int cmd; + + cmd = (nbl_need_check(vp)) ? F_SHARE_NBMAND : F_SHARE; + + /* + * Check if this is a metadata access + */ + + if ((desired_access & FILE_DATA_ALL) == 0) { + new_access |= F_MDACC; + } else { + if (desired_access & (ACE_READ_DATA | ACE_EXECUTE)) { + new_access |= F_RDACC; + flag |= FREAD; + } + + if (desired_access & (ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_ADD_FILE)) { + new_access |= F_WRACC; + flag |= FWRITE; + } + + if (SMB_DENY_READ(share_access)) { + deny |= F_RDDNY; + } + + if (SMB_DENY_WRITE(share_access)) { + deny |= F_WRDNY; + } + + if (cmd == F_SHARE_NBMAND) { + if (desired_access & ACE_DELETE) + new_access |= F_RMACC; + + if (SMB_DENY_DELETE(share_access)) { + deny |= F_RMDNY; + } + } + } + + shr.s_access = new_access; + shr.s_deny = deny; + shr.s_sysid = smb_ct.cc_sysid; + shr.s_pid = uniq_fid; + shr.s_own_len = sizeof (shr_own); + shr.s_owner = (caddr_t)&shr_own; + shr_own.sl_id = shr.s_sysid; + shr_own.sl_pid = shr.s_pid; + + return (VOP_SHRLOCK(vp, cmd, &shr, flag, cr, NULL)); +} + +int +smb_vop_unshrlock(vnode_t *vp, uint32_t uniq_fid, cred_t *cr) +{ + struct shrlock shr; + struct shr_locowner shr_own; + + /* + * For s_access and s_deny, we do not need to pass in the original + * values. + */ + + shr.s_access = 0; + shr.s_deny = 0; + shr.s_sysid = smb_ct.cc_sysid; + shr.s_pid = uniq_fid; + shr.s_own_len = sizeof (shr_own); + shr.s_owner = (caddr_t)&shr_own; + shr_own.sl_id = shr.s_sysid; + shr_own.sl_pid = shr.s_pid; + + return (VOP_SHRLOCK(vp, F_UNSHARE, &shr, 0, cr, NULL)); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c index 93b9f6e758..79a0ed82ec 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -78,8 +78,7 @@ smb_com_write(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -104,7 +103,7 @@ smb_com_write(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -151,8 +150,7 @@ smb_com_write_and_close(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -180,13 +178,13 @@ smb_com_write_and_close(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if ((rc = smb_common_close(sr, last_write)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -219,7 +217,7 @@ smb_com_write_and_unlock(struct smb_request *sr) int rc = 0; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -236,8 +234,7 @@ smb_com_write_and_unlock(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -259,7 +256,7 @@ smb_com_write_and_unlock(struct smb_request *sr) if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -267,7 +264,8 @@ smb_com_write_and_unlock(struct smb_request *sr) (uint64_t)param->w_count); if (result != NT_STATUS_SUCCESS) { kmem_free(param, sizeof (smb_write_param_t)); - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOTREACHED */ } @@ -324,15 +322,14 @@ smb_com_write_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if (SMB_WRMODE_IS_STABLE(param->w_mode) && STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ } @@ -349,7 +346,7 @@ smb_com_write_andx(struct smb_request *sr) if (param->w_count != 0) { if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } } @@ -381,10 +378,9 @@ smb_write_common(struct smb_request *sr, smb_write_param_t *param) if (node->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, node, param->w_offset, - param->w_count, FILE_WRITE_DATA); + param->w_count, B_TRUE); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, rc, ERRSRV, ERRaccess); /* NOTREACHED */ } } @@ -444,35 +440,49 @@ smb_write_truncate(struct smb_request *sr, smb_write_param_t *param) { struct smb_ofile *ofile = sr->fid_ofile; smb_node_t *node = ofile->f_node; + boolean_t append_only = B_FALSE; int rc; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) return (0); - if (node->attr.sa_vattr.va_type != VDIR) { - rc = smb_lock_range_access(sr, node, param->w_offset, - param->w_count, FILE_WRITE_DATA); + rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, FILE_WRITE_DATA); + if (rc != NT_STATUS_SUCCESS) { + rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, + FILE_APPEND_DATA); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + ERROR_ACCESS_DENIED); /* NOTREACHED */ + } else { + append_only = B_TRUE; } } - /* - * XXX what if the file has been opened only with - * FILE_APPEND_DATA? - */ - rc = smb_ofile_access(ofile, sr->user_cr, FILE_WRITE_DATA); - if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, - ERRDOS, ERROR_ACCESS_DENIED); + smb_rwx_xenter(&node->n_lock); + + if (append_only && (param->w_offset < node->n_size)) { + smb_rwx_xexit(&node->n_lock); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); /* NOTREACHED */ } + if (node->attr.sa_vattr.va_type != VDIR) { + rc = smb_lock_range_access(sr, node, param->w_offset, + param->w_count, B_TRUE); + if (rc != NT_STATUS_SUCCESS) { + smb_rwx_xexit(&node->n_lock); + smbsr_error(sr, rc, ERRSRV, ERRaccess); + /* NOTREACHED */ + } + } + node->flags |= NODE_FLAGS_SET_SIZE; node->n_size = param->w_offset; + smb_rwx_xexit(&node->n_lock); + if ((rc = smb_set_file_size(sr)) != 0) return (rc); diff --git a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c index 5d02179cc2..4c7fcb6f81 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -216,6 +216,7 @@ smb_com_write_raw(struct smb_request *sr) unsigned int stability; struct mbuf_chain reply; smb_node_t *fnode; + smb_error_t err; if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { return (SDRC_DROP_VC); @@ -244,8 +245,7 @@ smb_com_write_raw(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -260,10 +260,9 @@ smb_com_write_raw(struct smb_request *sr) */ if (fnode->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, fnode, off, - count, FILE_WRITE_DATA); + count, B_TRUE); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, rc, ERRSRV, ERRaccess); /* NOTREACHED */ } } @@ -440,8 +439,10 @@ notify_write_raw_complete: * If we had an error fill in the appropriate error code */ if (rc != 0) { - (void) smbsr_set_errno(sr, rc); + smbsr_map_errno(rc, &err); + smbsr_set_error(sr, &err); } + /* * Free raw write buffer if present (from smb_transfer_write_raw_data) */ diff --git a/usr/src/uts/common/smbsrv/cifs.h b/usr/src/uts/common/smbsrv/cifs.h index 4533a21bb6..1f657a2d8c 100644 --- a/usr/src/uts/common/smbsrv/cifs.h +++ b/usr/src/uts/common/smbsrv/cifs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -421,6 +421,23 @@ extern "C" { #define SMB_DA_WRITE_THROUGH 0x4000 /* + * Macros used for share reservation rule checking + */ + +#define SMB_DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0) + +#define SMB_DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0) + +#define SMB_DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0) + +#define SMB_DENY_RW(share_access) \ + ((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0) + +#define SMB_DENY_ALL(share_access) (share_access == 0) + +#define SMB_DENY_NONE(share_access) (share_access == FILE_SHARE_ALL) + +/* * The SMB open function determines what action should be taken depending * on the existence or lack thereof of files used in the operation. It * has the following mapping: diff --git a/usr/src/uts/common/smbsrv/lmshare.h b/usr/src/uts/common/smbsrv/lmshare.h index db41a5bdee..218bb86df8 100644 --- a/usr/src/uts/common/smbsrv/lmshare.h +++ b/usr/src/uts/common/smbsrv/lmshare.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -163,7 +163,6 @@ extern DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si); extern DWORD lmshrd_list(int offset, lmshare_list_t *list); extern DWORD lmshrd_list_transient(int offset, lmshare_list_t *list); extern DWORD lmshrd_num_transient(void); -extern int lmshrd_dump_hash(char *logfname); #endif extern int lmshrd_num_shares(void); extern DWORD lmshrd_delete(char *share_name); diff --git a/usr/src/uts/common/smbsrv/lmshare_door.h b/usr/src/uts/common/smbsrv/lmshare_door.h index c1c6f2ba0c..4e4413bc9a 100644 --- a/usr/src/uts/common/smbsrv/lmshare_door.h +++ b/usr/src/uts/common/smbsrv/lmshare_door.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,9 +70,9 @@ extern "C" { #define SMB_GET_KCONFIG 17 -void smb_load_kconfig(smb_kmod_cfg_t *cfg); -void smb_dr_get_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); -void smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); +void smb_load_kconfig(smb_kmod_cfg_t *); +void smb_dr_get_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); +void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); /* * Door server status @@ -97,17 +97,16 @@ void smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); * }; */ -void smb_dr_get_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si); -void smb_dr_put_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si); - -uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *ctx); -void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *ctx, - uint64_t lmshr_iter); -void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *ctx); -void smb_dr_get_lmshr_list(smb_dr_ctx_t *ctx, - lmshare_list_t *shrlist); -void smb_dr_put_lmshr_list(smb_dr_ctx_t *ctx, - lmshare_list_t *shrlist); +void smb_dr_get_lmshare(smb_dr_ctx_t *, lmshare_info_t *); +void smb_dr_put_lmshare(smb_dr_ctx_t *, lmshare_info_t *); + +uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *); +void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *, uint64_t); +void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *); +void smb_dr_get_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); +void smb_dr_put_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); + +void lmshrd_door_close(void); #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/lsalib.h b/usr/src/uts/common/smbsrv/lsalib.h index ae4076bf10..535fc9d62b 100644 --- a/usr/src/uts/common/smbsrv/lsalib.h +++ b/usr/src/uts/common/smbsrv/lsalib.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,31 +50,8 @@ extern "C" { /* * lsalib.c */ -int lsa_lookup_builtin_name(char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_local_sam(char *domain, - char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_local(char *name, - smb_userinfo_t *user_info); - -int lsa_lookup_name(char *server, - char *domain, - char *account_name, - smb_userinfo_t *user_info); - -DWORD lsa_lookup_name2(char *server, - char *domain, - char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_sid(nt_sid_t *sid, - smb_userinfo_t *user_info); - -DWORD lsa_lookup_sid2(nt_sid_t *sid, - smb_userinfo_t *user_info); +uint32_t lsa_lookup_name(char *, char *, uint16_t, smb_userinfo_t *); +uint32_t lsa_lookup_sid(nt_sid_t *, smb_userinfo_t *); int lsa_lookup_privs(char *server, char *account_name, @@ -111,11 +88,11 @@ int lsar_query_security_desc(mlsvc_handle_t *lsa_handle); DWORD lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass); -int lsar_lookup_names(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info); -int lsar_lookup_sids(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info); @@ -145,11 +122,11 @@ DWORD lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *display_name, int display_len); -DWORD lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info); -DWORD lsar_lookup_names2(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info); diff --git a/usr/src/uts/common/smbsrv/mlrpc.h b/usr/src/uts/common/smbsrv/mlrpc.h index 59ea5536fd..ff4d52254c 100644 --- a/usr/src/uts/common/smbsrv/mlrpc.h +++ b/usr/src/uts/common/smbsrv/mlrpc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -213,6 +213,21 @@ typedef struct mlrpc_service { } mlrpc_service_t; /* + * 20-byte opaque id used by various RPC services. + */ +typedef struct ndr_hdid { + uint32_t data[5]; +} ndr_hdid_t; + +typedef struct ndr_handle { + struct ndr_handle *nh_next; + ndr_hdid_t nh_id; + int nh_fid; + const mlrpc_service_t *nh_svc; + void *nh_data; +} ndr_handle_t; + +/* * The list of bindings is anchored at a connection. Nothing in the * RPC mechanism allocates them. Binding elements which have service==0 * indicate free elements. When a connection is instantiated, at least @@ -342,7 +357,8 @@ int mlrpc_heap_avail(mlrpc_heap_t *); #define MLRPC_HEAP_STRSAVE(MXA, STR) \ mlrpc_heap_strsave((MXA)->heap, (STR)) -struct mlrpc_xaction { +typedef struct mlrpc_xaction { + int fid; unsigned short ptype; /* just handy, hi bits spcl */ unsigned short opnum; /* for requests */ struct mlndr_stream recv_mlnds; @@ -353,7 +369,7 @@ struct mlrpc_xaction { struct mlrpc_binding *binding_list; /* from connection */ mlrpc_heap_t *heap; struct mlsvc_rpc_context *context; -}; +} ndr_xa_t; struct mlrpc_client { int (*xa_init)(struct mlrpc_client *, struct mlrpc_xaction *, @@ -371,16 +387,16 @@ struct mlrpc_client { unsigned next_p_cont_id; }; -/* mlndo.c */ +/* ndr_ops.c */ int mlnds_initialize(struct mlndr_stream *, unsigned, int, mlrpc_heap_t *); void mlnds_destruct(struct mlndr_stream *); -/* mlrpc_client.c */ +/* ndr_client.c */ int mlrpc_c_bind(struct mlrpc_client *, char *, struct mlrpc_binding **); int mlrpc_c_call(struct mlrpc_binding *, int, void *, mlrpc_heapref_t *); void mlrpc_c_free_heap(struct mlrpc_binding *, mlrpc_heapref_t *); -/* mlrpc_encdec.c */ +/* ndr_marshal.c */ int mlrpc_encode_decode_common(struct mlrpc_xaction *, int, unsigned, struct ndr_typeinfo *, void *); int mlrpc_decode_call(struct mlrpc_xaction *, void *); @@ -392,24 +408,30 @@ int mlrpc_encode_pdu_hdr(struct mlrpc_xaction *); void mlrpc_decode_frag_hdr(struct mlndr_stream *, mlrpcconn_common_header_t *); unsigned mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *); -/* mlrpc_server.c */ +/* ndr_server.c */ int mlrpc_generic_call_stub(struct mlrpc_xaction *); -/* mlrpc_svc.c */ -struct mlrpc_stub_table *mlrpc_find_stub_in_svc(struct mlrpc_service *, int); -struct mlrpc_service *mlrpc_find_service_by_name(const char *); -struct mlrpc_service *mlrpc_find_service_by_uuids(mlrpc_uuid_t *, int, - mlrpc_uuid_t *, int); -int mlrpc_register_service(struct mlrpc_service *); -void mlrpc_unregister_service(struct mlrpc_service *); -void mlrpc_uuid_to_str(mlrpc_uuid_t *, char *); -int mlrpc_str_to_uuid(char *, mlrpc_uuid_t *); +/* ndr_svc.c */ +struct mlrpc_stub_table *mlrpc_find_stub_in_svc(mlrpc_service_t *, int); +mlrpc_service_t *mlrpc_find_service_by_name(const char *); +mlrpc_service_t *mlrpc_find_service_by_uuids(ndr_uuid_t *, int, + ndr_uuid_t *, int); +int mlrpc_register_service(mlrpc_service_t *); +void mlrpc_unregister_service(mlrpc_service_t *); +void mlrpc_uuid_to_str(ndr_uuid_t *, char *); +int mlrpc_str_to_uuid(char *, ndr_uuid_t *); void mlrpc_binding_pool_initialize(struct mlrpc_binding **, struct mlrpc_binding pool[], unsigned); struct mlrpc_binding *mlrpc_find_binding(struct mlrpc_xaction *, mlrpc_p_context_id_t); struct mlrpc_binding *mlrpc_new_binding(struct mlrpc_xaction *); +ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *); +void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *); +ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *); +void ndr_hdclose(int fid); + + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/smbsrv/mlsvc.h b/usr/src/uts/common/smbsrv/mlsvc.h index 6177d9fbaf..a85066fc9f 100644 --- a/usr/src/uts/common/smbsrv/mlsvc.h +++ b/usr/src/uts/common/smbsrv/mlsvc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,17 +152,10 @@ char *mlsvc_ipc_name(int ipc_type, char *username); * the encrypted passwords. */ -int mlsvc_logon(char *domain_controller, char *domain_name, - char *username); -int mlsvc_echo(char *server); -int mlsvc_open_pipe(char *hostname, char *domain, char *username, - char *pipename); -int mlsvc_close_pipe(int fid); void mlsvc_nt_password_hash(char *result, char *password); int mlsvc_encrypt_nt_password(char *password, char *key, int keylen, char *out, int outmax); DWORD mlsvc_join(char *server, char *domain, char *username, char *password); -int mlsvc_locate_domain_controller(char *domain); /* * RPC request processing interface (mlsvc_server.c). @@ -198,16 +191,8 @@ typedef struct mlsvc_pipe { struct mlsvc_rpc_context *mlrpc_process(int, smb_dr_user_ctx_t *); struct mlsvc_rpc_context *mlrpc_lookup(int fid); void mlrpc_release(int); -int mlsvc_session_native_values(int fid, int *remote_os, int *remote_lm, - int *pdc_type); void mlsvc_rpc_report_status(int opnum, DWORD status); -/* - * This is a temporary location for this NETLOGON stuff. - */ -typedef int (*mlsvc_locate_pdc_t)(char *domain); -void mlsvc_install_pdc_cb(mlsvc_locate_pdc_t locate_pdc_cb); - #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/smbsrv/mlsvc_util.h b/usr/src/uts/common/smbsrv/mlsvc_util.h index e9ababec15..24e6bdd1a9 100644 --- a/usr/src/uts/common/smbsrv/mlsvc_util.h +++ b/usr/src/uts/common/smbsrv/mlsvc_util.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,72 +48,12 @@ extern "C" { #endif -/* - * Predefined global RIDs. - */ -#define MLSVC_DOMAIN_GROUP_RID_ADMINS 0x00000200L -#define MLSVC_DOMAIN_GROUP_RID_USERS 0x00000201L -#define MLSVC_DOMAIN_GROUP_RID_GUESTS 0x00000202L -#define MLSVC_DOMAIN_GROUP_RID_COMPUTERS 0x00000203L -#define MLSVC_DOMAIN_GROUP_RID_CONTROLLERS 0x00000204L -#define MLSVC_DOMAIN_GROUP_RID_CERT_ADMINS 0x00000205L -#define MLSVC_DOMAIN_GROUP_RID_SCHEMA_ADMINS 0x00000206L - -/* - * Predefined local alias RIDs. - */ -#define MLSVC_LOCAL_GROUP_RID_ADMINS 0x00000220L -#define MLSVC_LOCAL_GROUP_RID_USERS 0x00000221L -#define MLSVC_LOCAL_GROUP_RID_GUESTS 0x00000222L -#define MLSVC_LOCAL_GROUP_RID_POWER_USERS 0x00000223L -#define MLSVC_LOCAL_GROUP_RID_ACCOUNT_OPS 0x00000224L -#define MLSVC_LOCAL_GROUP_RID_SERVER_OPS 0x00000225L -#define MLSVC_LOCAL_GROUP_RID_PRINT_OPS 0x00000226L -#define MLSVC_LOCAL_GROUP_RID_BACKUP_OPS 0x00000227L -#define MLSVC_LOCAL_GROUP_RID_REPLICATOR 0x00000228L - -/* - * All predefined local group RIDs belong - * to a special domain called BUILTIN. - */ -#define MLSVC_BUILTIN_DOMAIN_NAME "BUILTIN" -#define MLSVC_BUILTIN_DOMAIN_SIDSTRLEN 8 - -/* - * Universal and NT well-known SIDs - */ -#define MLSVC_NULL_SIDSTR "S-1-0-0" -#define MSLVC_WORLD_SIDSTR "S-1-1-0" -#define MSLVC_LOCAL_SIDSTR "S-1-2-0" -#define MSLVC_CREATOR_OWNER_ID_SIDSTR "S-1-3-0" -#define MSLVC_CREATOR_GROUP_ID_SIDSTR "S-1-3-1" -#define MSLVC_CREATOR_OWNER_SERVER_ID_SIDSTR "S-1-3-2" -#define MSLVC_CREATOR_GROUP_SERVER_ID_SIDSTR "S-1-3-3" -#define MSLVC_NON_UNIQUE_IDS_SIDSTR "S-1-4" -#define MLSVC_NT_AUTHORITY_SIDSTR "S-1-5" -#define MLSVC_DIALUP_SIDSTR "S-1-5-1" -#define MLSVC_NETWORK_SIDSTR "S-1-5-2" -#define MLSVC_BATCH_SIDSTR "S-1-5-3" -#define MLSVC_INTERACTIVE_SIDSTR "S-1-5-4" -#define MLSVC_SERVICE_SIDSTR "S-1-5-6" -#define MLSVC_ANONYMOUS_LOGON_SIDSTR "S-1-5-7" -#define MLSVC_PROXY_SIDSTR "S-1-5-8" -#define MLSVC_SERVER_LOGON_SIDSTR "S-1-5-9" -#define MLSVC_SELF_SIDSTR "S-1-5-10" -#define MLSVC_AUTHENTICATED_USER_SIDSTR "S-1-5-11" -#define MLSVC_RESTRICTED_CODE_SIDSTR "S-1-5-12" -#define MLSVC_NT_LOCAL_SYSTEM_SIDSTR "S-1-5-18" -#define MLSVC_NT_NON_UNIQUE_SIDSTR "S-1-5-21" -#define MLSVC_BUILTIN_DOMAIN_SIDSTR "S-1-5-32" - -int mlsvc_lookup_name(char *domain, char *name, nt_sid_t **sid); -int mlsvc_lookup_sid(nt_sid_t *sid, char *buf, int bufsize); - smb_userinfo_t *mlsvc_alloc_user_info(void); void mlsvc_free_user_info(smb_userinfo_t *user_info); void mlsvc_release_user_info(smb_userinfo_t *user_info); void mlsvc_setadmin_user_info(smb_userinfo_t *user_info); char *mlsvc_sid_name_use(unsigned int snu_id); +extern int mlsvc_is_local_domain(const char *); /* * The definition of a local unique id (LUID). This is an opaque id @@ -148,38 +88,6 @@ typedef struct ms_handle { } ms_handle_t; /* - * List of interface specifications: can be used to identify the - * sub-system to which a handle is assigned. The handle management - * library doesn't check or care about the ifspec value. - */ -typedef enum ms_ifspec { - MLSVC_IFSPEC_NULL, - MLSVC_IFSPEC_LSAR, - MLSVC_IFSPEC_SAMR, - MLSVC_IFSPEC_WINREG, - MLSVC_IFSPEC_SVCCTL, - MLSVC_IFSPEC_SPOOLSS, - MLSVC_IFSPEC_LOGR, - MLSVC_IFSPEC_LLSR, - MLSVC_NUM_IFSPECS -} ms_ifspec_t; - -#define MLSVC_HANDLE_KEY_MAX 32 - -typedef struct ms_handle_desc { - struct ms_handle_desc *next; - ms_handle_t handle; - ms_ifspec_t ifspec; - char key[MLSVC_HANDLE_KEY_MAX]; - DWORD discrim; -} ms_handle_desc_t; - -ms_handle_t *mlsvc_get_handle(ms_ifspec_t ifspec, char *key, DWORD discrim); -int mlsvc_put_handle(ms_handle_t *handle); -int mlsvc_validate_handle(ms_handle_t *handle, char *key); -ms_handle_desc_t *mlsvc_lookup_handle(ms_handle_t *handle); - -/* * The mlsvc_rpc_context structure provides the connection binding context * for client RPC calls. This space must be provided by the client library * for use by the underlying RPC library. Note that we need two binding @@ -217,11 +125,6 @@ struct mlsvc_rpc_context { * The context contains a pointer to the top level handle for the * interface, which is assigned during the bind. It's used when closing * to detect when to free the context. - * - * I know this is really tacky but the elements in the descriptor are - * arranged so that a handle can be overlaid directly onto a descriptor. - * I probably won't do this but now you know - just in case you see it - * in the code. */ typedef struct mlsvc_rpc_desc { ms_handle_t handle; diff --git a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl index fd42fcac1c..596329a521 100644 --- a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl +++ b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,7 +46,7 @@ * UUID (Universal Unique IDentifier) */ /* (X/Open CAE Spec Appendix A) */ -struct mlrpc_uuid_dce { +struct ndr_dce_uuid { DWORD time_low; WORD time_mid; WORD time_hi_and_version; @@ -55,13 +55,13 @@ struct mlrpc_uuid_dce { BYTE node[6]; }; -struct mlrpc_uuid { +struct ndr_uuid { DWORD data1; WORD data2; WORD data3; BYTE data4[8]; }; -typedef struct mlrpc_uuid mlrpc_uuid_t; +typedef struct ndr_uuid ndr_uuid_t; /* * Representation label -- needed for RPC header @@ -171,7 +171,7 @@ typedef WORD mlrpc_p_context_id_t; _NO_REORDER_ struct mlrpc_p_syntax_id { - mlrpc_uuid_t if_uuid; + ndr_uuid_t if_uuid; DWORD if_version; }; typedef struct mlrpc_p_syntax_id mlrpc_p_syntax_id_t; @@ -182,7 +182,7 @@ struct mlrpc_p_cont_elem { BYTE n_transfer_syn; BYTE _reserved; mlrpc_p_syntax_id_t abstract_syntax; - /*SIZE_IS(n_transfer_syn)*/ + /*SIZE_IS(n_transfer_syn)*/ mlrpc_p_syntax_id_t transfer_syntaxes[1]; }; typedef struct mlrpc_p_cont_elem mlrpc_p_cont_elem_t; @@ -193,7 +193,7 @@ struct mlrpc_p_cont_list { BYTE n_context_elem; BYTE _reserved; WORD _reserved2; - /*SIZE_IS(n_context_elem)*/ + /*SIZE_IS(n_context_elem)*/ mlrpc_p_cont_elem_t p_cont_elem[1]; }; typedef struct mlrpc_p_cont_list mlrpc_p_cont_list_t; @@ -226,7 +226,7 @@ struct mlrpc_p_result_list { BYTE n_results; BYTE reserved; WORD reserved2; - /*SIZE_IS(n_results)*/ + /*SIZE_IS(n_results)*/ mlrpc_p_result_t p_results[1]; }; typedef struct mlrpc_p_result_list mlrpc_p_result_list_t; @@ -236,10 +236,10 @@ EXTERNTYPEINFO(mlrpc_p_result_list) _NO_REORDER_ struct mlrpc_port_any { WORD length; /* always 18 */ - /*SIZE_IS(length)*/ + /*SIZE_IS(length)*/ BYTE port_spec[MLRPC_PORT_ANY_MAX_PORT_SPEC]; - /* \PIPE\ntsvcs */ - /* We cheat by using 18, and pad on the right with zeroes */ + /* \PIPE\ntsvcs */ + /* We cheat by using 18, and pad on the right with zeroes */ }; typedef struct mlrpc_port_any mlrpc_port_any_t; EXTERNTYPEINFO(mlrpc_port_any) @@ -377,15 +377,15 @@ _NO_REORDER_ struct mlrpcconn_request_hdr { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ WORD opnum; /* 22:02 op number w/i interface */ - /* optional field if PFC_OBJECT_UUID, not present */ - /* mlrpc_uuid_t object; */ + /* optional field if PFC_OBJECT_UUID, not present */ + /* ndr_uuid_t object; */ /* stub-data, 8-octet aligned */ /* 24:nn */ /* nn = frag_len - sizeof(common_header) - auth_len */ @@ -399,19 +399,19 @@ _NO_REORDER_ struct mlrpcconn_request_hdr_with_object { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ WORD opnum; /* 22:02 op number w/i interface */ - /* optional field if PFC_OBJECT_UUID, is present */ - mlrpc_uuid_t object; /* 24:16 object UUID, unknown purpose*/ + /* optional field if PFC_OBJECT_UUID, is present */ + ndr_uuid_t object; /* 24:16 object UUID, unknown purpose*/ /* stub-data, 8-octet aligned */ /* 28:nn */ /* nn = frag_len - sizeof(common_header) - auth_len */ - /* nn -= sizeof(mlrpc_uuid_t); */ + /* nn -= sizeof(ndr_uuid_t); */ /* optional authentication verifier iff auth_length != 0 */ /* auth_verifier_co_t auth_verifier; */ @@ -435,12 +435,12 @@ _NO_REORDER_ struct mlrpcconn_response_hdr { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ - /* needed for response or fault */ + /* needed for response or fault */ BYTE cancel_count; /* 22:01 cancel count */ BYTE reserved; /* 23:01 mbz */ @@ -467,17 +467,17 @@ struct mlrpcconn_fault_hdr { mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ - /* needed for response or fault */ + /* needed for response or fault */ BYTE cancel_count; /* 22:01 cancel count */ BYTE reserved; /* 23:01 mbz */ - /* fault code */ + /* fault code */ DWORD status; /* 24:04 run-time fault code or 0 */ - /* pad to 8-byte alignment */ + /* pad to 8-byte alignment */ BYTE reserved2[4]; /* 28:04 must-be-zero */ - /* stub-data here if status==0. We do not use this mode. */ + /* stub-data here if status==0. We do not use this mode. */ /* optional authentication verifier iff auth_length != 0 */ /* auth_verifier_co_t auth_verifier; */ diff --git a/usr/src/uts/common/smbsrv/ndl/winreg.ndl b/usr/src/uts/common/smbsrv/ndl/winreg.ndl index 2d3d1de28d..b1a02a858b 100644 --- a/usr/src/uts/common/smbsrv/ndl/winreg.ndl +++ b/usr/src/uts/common/smbsrv/ndl/winreg.ndl @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,7 +34,10 @@ #include "ndrtypes.ndl" +#define WINREG_OPNUM_OpenHKCR 0x00 +#define WINREG_OPNUM_OpenHKCU 0x01 #define WINREG_OPNUM_OpenHKLM 0x02 +#define WINREG_OPNUM_OpenHKPD 0x03 #define WINREG_OPNUM_OpenHKUsers 0x04 #define WINREG_OPNUM_Close 0x05 #define WINREG_OPNUM_CreateKey 0x06 @@ -44,34 +47,40 @@ #define WINREG_OPNUM_EnumValue 0x0a #define WINREG_OPNUM_FlushKey 0x0b #define WINREG_OPNUM_GetKeySec 0x0c +#define WINREG_OPNUM_LoadKey 0x0d +#define WINREG_OPNUM_NotifyChange 0x0e #define WINREG_OPNUM_OpenKey 0x0f #define WINREG_OPNUM_QueryKey 0x10 #define WINREG_OPNUM_QueryValue 0x11 +#define WINREG_OPNUM_ReplaceKey 0x12 +#define WINREG_OPNUM_RestoreKey 0x13 +#define WINREG_OPNUM_SaveKey 0x14 #define WINREG_OPNUM_SetKeySec 0x15 #define WINREG_OPNUM_CreateValue 0x16 +#define WINREG_OPNUM_UnloadKey 0x17 #define WINREG_OPNUM_Shutdown 0x18 +#define WINREG_OPNUM_AbortShutdown 0x19 #define WINREG_OPNUM_GetVersion 0x1a - -struct msreg_handle { +struct winreg_handle { DWORD hand1; DWORD hand2; WORD hand3[2]; BYTE hand4[8]; }; -typedef struct msreg_handle msreg_handle_t; +typedef struct winreg_handle winreg_handle_t; -struct msreg_string_desc { +struct winreg_string_desc { WORD length; WORD allosize; LPTSTR str; }; -typedef struct msreg_string_desc msreg_string_t; +typedef struct winreg_string_desc winreg_string_t; /* * Fake Varying/Conformant with a funny conformant. */ -struct msreg_value { +struct winreg_value { DWORD vc_first_is; /* 0 */ DWORD vc_length_is; SIZE_IS(vc_length_is) @@ -84,37 +93,59 @@ struct file_time { }; typedef struct file_time file_time_t; +OPERATION(WINREG_OPNUM_OpenHKCR) +struct winreg_OpenHKCR { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_OpenHKCU) +struct winreg_OpenHKCU { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenHKLM) -struct msreg_OpenHKLM { - IN BYTE whatever[8]; +struct winreg_OpenHKLM { + IN DWORD *server; IN DWORD access_mask; - OUT msreg_handle_t handle; + OUT winreg_handle_t handle; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_OpenHKPD) +struct winreg_OpenHKPD { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenHKUsers) -struct msreg_OpenHKUsers { - IN BYTE whatever[8]; +struct winreg_OpenHKUsers { + IN DWORD *server; IN DWORD access_mask; - OUT msreg_handle_t handle; + OUT winreg_handle_t handle; OUT DWORD status; }; OPERATION(WINREG_OPNUM_Close) -struct msreg_Close { - IN msreg_handle_t handle; - OUT msreg_handle_t result_handle; +struct winreg_Close { + IN winreg_handle_t handle; + OUT winreg_handle_t result_handle; OUT DWORD status; }; OPERATION(WINREG_OPNUM_CreateKey) -struct msreg_CreateKey { - IN msreg_handle_t handle; - IN msreg_string_t subkey; +struct winreg_CreateKey { + IN winreg_handle_t handle; + IN winreg_string_t subkey; /* IN ignore the remaining input data */ OUT DWORD status; @@ -122,9 +153,9 @@ struct msreg_CreateKey { OPERATION(WINREG_OPNUM_DeleteKey) -struct msreg_DeleteKey { - IN msreg_handle_t handle; - IN msreg_string_t subkey; +struct winreg_DeleteKey { + IN winreg_handle_t handle; + IN winreg_string_t subkey; /* IN ignore the remaining input data */ OUT DWORD status; @@ -132,9 +163,9 @@ struct msreg_DeleteKey { OPERATION(WINREG_OPNUM_DeleteValue) -struct msreg_DeleteValue { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_DeleteValue { + IN winreg_handle_t handle; + IN winreg_string_t name; /* IN ignore the remaining input data */ OUT DWORD status; @@ -146,27 +177,48 @@ struct msreg_DeleteValue { * as IN parameters but we can ignore them. */ OPERATION(WINREG_OPNUM_EnumValue) -struct msreg_EnumValue { - IN msreg_handle_t handle; - IN DWORD index; +struct winreg_EnumValue { + IN winreg_handle_t handle; + IN DWORD index; /* IN ignore the remaining input data */ - OUT msreg_string_t name; + OUT winreg_string_t name; OUT DWORD *type; - OUT struct msreg_value *value; + OUT struct winreg_value *value; OUT DWORD *value_size; OUT DWORD *value_size_total; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_FlushKey) +struct winreg_FlushKey { + IN winreg_handle_t handle; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_GetKeySec) +struct winreg_GetKeySec { + IN winreg_handle_t handle; + IN DWORD sec_info; + OUT DWORD *sd; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_NotifyChange) +struct winreg_NotifyChange { + IN winreg_handle_t handle; + IN DWORD watch_subtree; + IN DWORD notify_filter; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenKey) -struct msreg_OpenKey { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_OpenKey { + IN winreg_handle_t handle; + IN winreg_string_t name; IN DWORD unknown; IN DWORD access_mask; - OUT msreg_handle_t result_handle; + OUT winreg_handle_t result_handle; OUT DWORD status; }; @@ -183,14 +235,14 @@ struct msreg_OpenKey { */ OPERATION(WINREG_OPNUM_QueryKey) -struct msreg_QueryKey { - IN msreg_handle_t handle; +struct winreg_QueryKey { + IN winreg_handle_t handle; /* * Ignore the remaining input data - * (2 * DWORD, possibly msreg_string_t). + * (2 * DWORD, possibly winreg_string_t). */ - OUT msreg_string_t name; + OUT winreg_string_t name; OUT DWORD unknown; OUT DWORD sub_keys; OUT DWORD max_subkey_len; @@ -209,23 +261,31 @@ struct msreg_QueryKey { * as IN parameters but we can ignore them. */ OPERATION(WINREG_OPNUM_QueryValue) -struct msreg_QueryValue { - IN msreg_handle_t handle; - IN msreg_string_t value_name; +struct winreg_QueryValue { + IN winreg_handle_t handle; + IN winreg_string_t value_name; /* IN ignore the remaining input data */ OUT DWORD *type; - OUT struct msreg_value *value; + OUT struct winreg_value *value; OUT DWORD *value_size; OUT DWORD *value_size_total; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_SetKeySec) +struct winreg_SetKeySec { + IN winreg_handle_t handle; + IN DWORD access_mask; + IN DWORD sd; + OUT DWORD status; +}; + OPERATION(WINREG_OPNUM_CreateValue) -struct msreg_CreateValue { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_CreateValue { + IN winreg_handle_t handle; + IN winreg_string_t name; /* IN ignore the remaining input data */ OUT DWORD status; @@ -238,17 +298,17 @@ struct msreg_CreateValue { * without anything appearing in the log, and return access denied. */ OPERATION(WINREG_OPNUM_Shutdown) -struct msreg_Shutdown { - IN DWORD ignored; - OUT DWORD status; +struct winreg_Shutdown { + IN DWORD ignored; + OUT DWORD status; }; OPERATION(WINREG_OPNUM_GetVersion) -struct msreg_GetVersion { - IN msreg_handle_t handle; - OUT DWORD version; - OUT DWORD status; +struct winreg_GetVersion { + IN winreg_handle_t handle; + OUT DWORD version; + OUT DWORD status; }; @@ -257,30 +317,44 @@ struct msreg_GetVersion { */ INTERFACE(0) union winreg_interface { + CASE(WINREG_OPNUM_OpenHKCR) + struct winreg_OpenHKCR OpenHKCR; + CASE(WINREG_OPNUM_OpenHKCU) + struct winreg_OpenHKCU OpenHKCU; CASE(WINREG_OPNUM_OpenHKLM) - struct msreg_OpenHKLM OpenHKLM; + struct winreg_OpenHKLM OpenHKLM; + CASE(WINREG_OPNUM_OpenHKPD) + struct winreg_OpenHKPD OpenHKPD; CASE(WINREG_OPNUM_OpenHKUsers) - struct msreg_OpenHKUsers OpenHKUsers; + struct winreg_OpenHKUsers OpenHKUsers; CASE(WINREG_OPNUM_Close) - struct msreg_Close Close; + struct winreg_Close Close; CASE(WINREG_OPNUM_CreateKey) - struct msreg_CreateKey CreateKey; + struct winreg_CreateKey CreateKey; CASE(WINREG_OPNUM_DeleteKey) - struct msreg_DeleteKey DeleteKey; + struct winreg_DeleteKey DeleteKey; CASE(WINREG_OPNUM_DeleteValue) - struct msreg_DeleteValue DeleteValue; + struct winreg_DeleteValue DeleteValue; + CASE(WINREG_OPNUM_FlushKey) + struct winreg_FlushKey FlushKey; + CASE(WINREG_OPNUM_GetKeySec) + struct winreg_GetKeySec GetKeySec; + CASE(WINREG_OPNUM_NotifyChange) + struct winreg_NotifyChange NotifyChange; CASE(WINREG_OPNUM_OpenKey) - struct msreg_OpenKey OpenKey; + struct winreg_OpenKey OpenKey; CASE(WINREG_OPNUM_QueryKey) - struct msreg_QueryKey QueryKey; + struct winreg_QueryKey QueryKey; CASE(WINREG_OPNUM_QueryValue) - struct msreg_QueryValue QueryValue; + struct winreg_QueryValue QueryValue; + CASE(WINREG_OPNUM_SetKeySec) + struct winreg_SetKeySec SetKeySec; CASE(WINREG_OPNUM_CreateValue) - struct msreg_CreateValue CreateValue; + struct winreg_CreateValue CreateValue; CASE(WINREG_OPNUM_Shutdown) - struct msreg_Shutdown Shutdown; + struct winreg_Shutdown Shutdown; CASE(WINREG_OPNUM_GetVersion) - struct msreg_GetVersion GetVersion; + struct winreg_GetVersion GetVersion; }; typedef union winreg_interface winreg_interface_t; EXTERNTYPEINFO(winreg_interface) diff --git a/usr/src/uts/common/smbsrv/samlib.h b/usr/src/uts/common/smbsrv/samlib.h index efec26a922..c38986d1d5 100644 --- a/usr/src/uts/common/smbsrv/samlib.h +++ b/usr/src/uts/common/smbsrv/samlib.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,7 +55,7 @@ DWORD sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth); DWORD sam_create_account(char *server, char *domain_name, char *account_name, - smb_auth_info_t *auth, DWORD account_flags, smb_userinfo_t *user_info); + smb_auth_info_t *auth, DWORD account_flags); DWORD sam_remove_trust_account(char *server, char *domain); diff --git a/usr/src/uts/common/smbsrv/smb_door_svc.h b/usr/src/uts/common/smbsrv/smb_door_svc.h index be8898f42a..6b9b943a6a 100644 --- a/usr/src/uts/common/smbsrv/smb_door_svc.h +++ b/usr/src/uts/common/smbsrv/smb_door_svc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -82,20 +82,8 @@ enum smb_dr_opcode_t { SMB_DR_USER_NONAUTH_LOGON, SMB_DR_USER_AUTH_LOGOFF, SMB_DR_USER_LIST, - SMB_DR_GROUP_ADD, - SMB_DR_GROUP_DELETE, - SMB_DR_GROUP_MEMBER_ADD, - SMB_DR_GROUP_MEMBER_REMOVE, - SMB_DR_GROUP_COUNT, - SMB_DR_GROUP_CACHE_SIZE, - SMB_DR_GROUP_MODIFY, - SMB_DR_GROUP_PRIV_NUM, - SMB_DR_GROUP_PRIV_LIST, - SMB_DR_GROUP_PRIV_GET, - SMB_DR_GROUP_PRIV_SET, - SMB_DR_GROUP_LIST, - SMB_DR_GROUP_MEMBER_LIST, - SMB_DR_GROUP_MEMBER_COUNT + SMB_DR_LOOKUP_SID, + SMB_DR_LOOKUP_NAME }; enum smb_kdr_opcode_t { diff --git a/usr/src/uts/common/smbsrv/smb_fsops.h b/usr/src/uts/common/smbsrv/smb_fsops.h index afed8b6637..07e825c24d 100644 --- a/usr/src/uts/common/smbsrv/smb_fsops.h +++ b/usr/src/uts/common/smbsrv/smb_fsops.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,11 +36,15 @@ #include <smbsrv/smbinfo.h> #include <smbsrv/smb_vops.h> #include <smbsrv/smbvar.h> +#include <sys/callb.h> +#include <sys/flock.h> #ifdef __cplusplus extern "C" { #endif +extern caller_context_t smb_ct; + int smb_fsop_open(smb_ofile_t *of); int smb_fsop_close(smb_ofile_t *of); @@ -119,7 +123,13 @@ int smb_fsop_sdread(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *); int smb_fsop_sdwrite(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *, int); -void smb_get_caller_context(smb_request_t *sr, caller_context_t *ct); +uint32_t smb_fsop_shrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid, + uint32_t desired_access, uint32_t share_access); + +void smb_fsop_unshrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid); + +int smb_fsop_frlock(smb_request_t *sr, smb_node_t *node, smb_lock_t *lock, + boolean_t unlock); /* * Lookup-related flags diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 0b9442bed1..a23b42572c 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -101,10 +101,12 @@ void smb_release_oplock(struct smb_ofile *file, int reason); uint32_t smb_unlock_range(struct smb_request *, struct smb_node *, uint64_t, uint64_t); -void smb_unlock_range_raise_error(smb_request_t *sr, uint32_t ntstatus); uint32_t smb_lock_range(struct smb_request *, struct smb_ofile *, uint64_t, uint64_t, uint32_t, uint32_t); -void smb_lock_range_raise_error(smb_request_t *sr, uint32_t ntstatus); +void smb_lock_range_error(smb_request_t *, uint32_t); + +DWORD smb_range_check(smb_request_t *, cred_t *, smb_node_t *, + uint64_t, uint64_t, boolean_t); int smb_mangle_name(ino64_t fileid, char *name, char *shortname, char *name83, int force); @@ -149,31 +151,17 @@ void smbsr_decode_error(struct smb_request *); void smbsr_encode_error(struct smb_request *); void smbsr_encode_empty_result(struct smb_request *sr); -#pragma does_not_return(smbsr_decode_error) -#pragma does_not_return(smbsr_encode_error) - int smbsr_decode_vwv(struct smb_request *sr, char *fmt, ...); int smbsr_decode_data(struct smb_request *sr, char *fmt, ...); void smbsr_encode_result(struct smb_request *, int, int, char *, ...); smb_xa_t *smbsr_lookup_xa(smb_request_t *sr); void smbsr_send_reply(struct smb_request *); -void smbsr_raise_cifs_error(struct smb_request *sr, DWORD status, - int error_class, int error_code); - -int smbsr_set_errno(struct smb_request *, int); -void smbsr_raise_errno(struct smb_request *, int); -void smbsr_raise_error(struct smb_request *, int, int); -void smbsr_raise_nt_error(struct smb_request *sr, uint32_t); - -#pragma does_not_return(smbsr_raise_cifs_error) -#pragma does_not_return(smbsr_raise_error) -#pragma does_not_return(smbsr_raise_nt_error) -#pragma does_not_return(smbsr_raise_errno) - -void smbsr_setup_nt_status(struct smb_request *sr, - uint32_t severity, - uint32_t nt_status); +void smbsr_map_errno(int, smb_error_t *); +void smbsr_set_error(smb_request_t *, smb_error_t *); +void smbsr_errno(struct smb_request *, int); +void smbsr_warn(struct smb_request *, DWORD, uint16_t, uint16_t); +void smbsr_error(struct smb_request *, DWORD, uint16_t, uint16_t); int smb_mbc_encode(struct mbuf_chain *mbc, char *fmt, va_list ap); int smb_mbc_decode(struct mbuf_chain *mbc, char *fmt, va_list ap); @@ -202,7 +190,7 @@ int smb_component_match(struct smb_request *sr, ino64_t fileid, struct smb_odir *od, smb_odir_context_t *pc); int smb_lock_range_access(struct smb_request *, struct smb_node *, - uint64_t, uint64_t, uint32_t desired_access); + uint64_t, uint64_t, boolean_t); uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); @@ -247,6 +235,17 @@ void smb_node_root_fini(); void smb_node_add_lock(smb_node_t *node, smb_lock_t *lock); void smb_node_destroy_lock(smb_node_t *node, smb_lock_t *lock); void smb_node_destroy_lock_by_ofile(smb_node_t *node, smb_ofile_t *file); +void smb_node_start_crit(smb_node_t *node, krw_t mode); +void smb_node_end_crit(smb_node_t *node); +int smb_node_in_crit(smb_node_t *node); + +uint32_t smb_node_open_check(smb_node_t *, cred_t *, + uint32_t, uint32_t); +uint32_t smb_node_share_check(smb_node_t *, cred_t *, + uint32_t, uint32_t, smb_ofile_t *); +DWORD smb_node_rename_check(smb_node_t *); +DWORD smb_node_delete_check(smb_node_t *); + uint64_t smb_node_get_size(smb_node_t *node, smb_attr_t *attr); void smb_node_set_time(struct smb_node *node, timestruc_t *crtime, timestruc_t *mtime, timestruc_t *atime, @@ -359,7 +358,6 @@ int smb_stream_parse_name(char *name, char *u_stream_name, uint32_t smb_get_gmtoff(void); void smb_set_gmtoff(uint32_t); -void smb_errmap_unix2smb(int en, smb_error_t *smberr); DWORD smb_trans2_set_information(struct smb_request *sr, smb_trans2_setinfo_t *info, smb_error_t *smberr); @@ -398,7 +396,8 @@ void smb_session_disconnect_volume(fs_desc_t *); smb_ofile_t *smb_ofile_lookup_by_fid(smb_tree_t *tree, uint16_t fid); smb_ofile_t *smb_ofile_open(smb_tree_t *tree, smb_node_t *node, uint16_t pid, uint32_t access_granted, uint32_t create_options, uint32_t share_access, - uint16_t ftype, char *pipe_name, uint32_t rpc_fid, smb_error_t *err); + uint16_t ftype, char *pipe_name, uint32_t rpc_fid, uint32_t uniqid, + smb_error_t *err); int smb_ofile_close(smb_ofile_t *ofile, uint32_t last_wtime); uint32_t smb_ofile_access(smb_ofile_t *ofile, cred_t *cr, uint32_t access); int smb_ofile_seek(smb_ofile_t *of, ushort_t mode, int32_t off, diff --git a/usr/src/uts/common/smbsrv/smb_privilege.h b/usr/src/uts/common/smbsrv/smb_privilege.h index c03455d469..9fad667938 100644 --- a/usr/src/uts/common/smbsrv/smb_privilege.h +++ b/usr/src/uts/common/smbsrv/smb_privilege.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -98,6 +98,7 @@ extern "C" { #define SE_CHANGE_NOTIFY_NAME "SeChangeNotifyPrivilege" #define SE_REMOTE_SHUTDOWN_NAME "SeRemoteShutdownPrivilege" +#define SE_MIN_LUID 2 #define SE_CREATE_TOKEN_LUID 2 #define SE_ASSIGNPRIMARYTOKEN_LUID 3 #define SE_LOCK_MEMORY_LUID 4 @@ -121,6 +122,7 @@ extern "C" { #define SE_SYSTEM_ENVIRONMENT_LUID 22 #define SE_CHANGE_NOTIFY_LUID 23 #define SE_REMOTE_SHUTDOWN_LUID 24 +#define SE_MAX_LUID 24 /* * Privilege attributes @@ -181,6 +183,7 @@ int smb_privset_size(); void smb_privset_init(smb_privset_t *privset); void smb_privset_free(smb_privset_t *privset); void smb_privset_copy(smb_privset_t *dst, smb_privset_t *src); +void smb_privset_merge(smb_privset_t *dst, smb_privset_t *src); void smb_privset_enable(smb_privset_t *privset, uint32_t id); int smb_privset_query(smb_privset_t *privset, uint32_t id); void smb_privset_log(smb_privset_t *privset); diff --git a/usr/src/uts/common/smbsrv/smb_vops.h b/usr/src/uts/common/smbsrv/smb_vops.h index 3b09c99b63..0f98b41be5 100644 --- a/usr/src/uts/common/smbsrv/smb_vops.h +++ b/usr/src/uts/common/smbsrv/smb_vops.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -318,67 +318,53 @@ struct fs_stream_info { int fhopen(const struct smb_node *, int); -extern int smb_vop_open(vnode_t **vpp, int mode, cred_t *cred, - caller_context_t *ct); -extern int smb_vop_close(vnode_t *vp, int flag, cred_t *cred, - caller_context_t *ct); -extern int smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_write(vnode_t *vp, uio_t *uiop, unsigned int *flag, - uint32_t *lcount, cred_t *cr, caller_context_t *ct); -extern int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, - smb_attr_t *ret_attr, int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, - smb_attr_t *set_attr, int flags, cred_t *cr, boolean_t no_xvattr, - caller_context_t *ct); -extern int smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, - cred_t *cr); -extern void smb_vop_eaccess(vnode_t *vp, int *mode, int flags, vnode_t *dir_vp, - cred_t *cr); -extern int smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, - char *od_name, int flags, vnode_t *rootvp, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, - vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct, - vsecattr_t *vsap); -extern int smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, - char *to_name, int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, - vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct, - vsecattr_t *vsap); -extern int smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, - int *namelen, ino64_t *inop, vnode_t **vpp, char *od_name, int flags, - cred_t *cr, caller_context_t *ct); -extern int smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct); -extern int smb_vop_getdents(struct smb_node *dir_snode, uint32_t *cookiep, - uint64_t *verifierp, int32_t *dircountp, char *arg, char *pattern, - uint32_t flags, struct smb_request *sr, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr); -extern int smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, - vnode_t **vpp, char *name, vnode_t **xattrdirvpp, int flags, - vnode_t *rootvp, cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_create(vnode_t *fvp, char *stream_name, - smb_attr_t *attr, vnode_t **vpp, vnode_t **xattrdirvpp, int flags, - cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, - cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, - struct fs_stream_info *stream_info, vnode_t **vpp, vnode_t **xattrdirvp, - int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, - int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_traverse_check(vnode_t **vpp); - -int smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, - cred_t *cr, caller_context_t *ct); -int smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, - caller_context_t *ct); -acl_type_t smb_vop_acl_type(vnode_t *vp); +extern void smb_vop_start(void); +extern int smb_vop_open(vnode_t **, int, cred_t *); +extern int smb_vop_close(vnode_t *, int, cred_t *); +extern int smb_vop_read(vnode_t *, uio_t *, cred_t *); +extern int smb_vop_write(vnode_t *, uio_t *, unsigned int *, + uint32_t *, cred_t *); +extern int smb_vop_getattr(vnode_t *, vnode_t *, + smb_attr_t *, int, cred_t *); +extern int smb_vop_setattr(vnode_t *, vnode_t *, + smb_attr_t *, int, cred_t *, boolean_t); +extern int smb_vop_access(vnode_t *, int, int, vnode_t *, + cred_t *); +extern void smb_vop_eaccess(vnode_t *, int *, int, vnode_t *, + cred_t *); +extern int smb_vop_lookup(vnode_t *, char *, vnode_t **, + char *, int, vnode_t *, cred_t *); +extern int smb_vop_create(vnode_t *, char *, smb_attr_t *, + vnode_t **, int, cred_t *, vsecattr_t *); +extern int smb_vop_remove(vnode_t *, char *, int, cred_t *); +extern int smb_vop_rename(vnode_t *, char *, vnode_t *, + char *, int, cred_t *); +extern int smb_vop_mkdir(vnode_t *, char *, smb_attr_t *, + vnode_t **, int, cred_t *, vsecattr_t *); +extern int smb_vop_rmdir(vnode_t *, char *, int, cred_t *); +extern int smb_vop_readdir(vnode_t *, uint32_t *, char *, + int *, ino64_t *, vnode_t **, char *, int, cred_t *); +extern int smb_vop_commit(vnode_t *, cred_t *); +extern int smb_vop_getdents(struct smb_node *, uint32_t *, + uint64_t *, int32_t *, char *, char *, + uint32_t, struct smb_request *, cred_t *); +extern int smb_vop_statfs(vnode_t *, struct statvfs64 *, cred_t *); +extern int smb_vop_stream_lookup(vnode_t *, char *, + vnode_t **, char *, vnode_t **, int, vnode_t *, cred_t *); +extern int smb_vop_stream_create(vnode_t *, char *, + smb_attr_t *, vnode_t **, vnode_t **, int, cred_t *); +extern int smb_vop_stream_remove(vnode_t *, char *, int, cred_t *); +extern int smb_vop_stream_readdir(vnode_t *, uint32_t *, + struct fs_stream_info *, vnode_t **, vnode_t **, int, cred_t *); +extern int smb_vop_lookup_xattrdir(vnode_t *, vnode_t **, int, cred_t *); +extern int smb_vop_traverse_check(vnode_t **); + +int smb_vop_acl_read(vnode_t *, acl_t **, int, acl_type_t, cred_t *); +int smb_vop_acl_write(vnode_t *, acl_t *, int, cred_t *); +acl_type_t smb_vop_acl_type(vnode_t *); + +int smb_vop_shrlock(vnode_t *, uint32_t, uint32_t, uint32_t, cred_t *); +int smb_vop_unshrlock(vnode_t *, uint32_t, cred_t *); #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smbinfo.h b/usr/src/uts/common/smbsrv/smbinfo.h index 2426b54b61..01404f3a55 100644 --- a/usr/src/uts/common/smbsrv/smbinfo.h +++ b/usr/src/uts/common/smbsrv/smbinfo.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -127,18 +127,17 @@ typedef struct smb_kmod_cfg { uint32_t skc_maxworkers; uint32_t skc_maxconnections; uint32_t skc_keepalive; - uint32_t skc_restrict_anon; - uint32_t skc_signing_enable; - uint32_t skc_signing_required; - uint32_t skc_signing_check; - uint32_t skc_oplock_enable; uint32_t skc_oplock_timeout; - uint32_t skc_flush_required; - uint32_t skc_sync_enable; - uint32_t skc_dirsymlink_enable; - uint32_t skc_announce_quota; - uint32_t skc_secmode; - uint32_t skc_lmlevel; + int32_t skc_restrict_anon; + int32_t skc_signing_enable; + int32_t skc_signing_required; + int32_t skc_signing_check; + int32_t skc_oplock_enable; + int32_t skc_flush_required; + int32_t skc_sync_enable; + int32_t skc_dirsymlink_enable; + int32_t skc_announce_quota; + int32_t skc_secmode; char skc_resource_domain[SMB_PI_MAX_DOMAIN]; char skc_hostname[SMB_PI_MAX_HOST]; @@ -173,7 +172,6 @@ int smbnative_pdc_value(char *native_lm); #define SMBD_DOOR_PARAM_GET 2 #define SMBD_DOOR_PARAM_SET 3 #define SMBD_DOOR_NETBIOS_RECONFIG 4 -#define SMBD_DOOR_ADS_DOMAIN_CHANGED 5 #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smbvar.h b/usr/src/uts/common/smbsrv/smbvar.h index edcfbe7187..f4e11582a0 100644 --- a/usr/src/uts/common/smbsrv/smbvar.h +++ b/usr/src/uts/common/smbsrv/smbvar.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -389,6 +389,7 @@ typedef enum { typedef struct smb_node { uint32_t n_magic; smb_rwx_t n_lock; + krwlock_t n_share_lock; list_node_t n_lnd; smb_node_state_t n_state; uint32_t n_refcnt; @@ -835,6 +836,7 @@ typedef struct smb_ofile { mlsvc_pipe_t *f_pipe_info; + uint32_t f_uniqid; uint32_t f_refcnt; uint64_t f_seek_pos; uint32_t f_flags; @@ -1198,11 +1200,8 @@ struct smb_request { label_t exjb; cred_t *user_cr; - caller_context_t ct; }; -caller_context_t local_ct; - #define SMB_READ_PROTOCOL(smb_nh_ptr) \ LE_IN32(((smb_nethdr_t *)(smb_nh_ptr))->sh_protocol) @@ -1317,6 +1316,7 @@ typedef struct smb_info { volatile uint64_t si_global_kid; volatile uint32_t si_gmtoff; + volatile uint32_t si_uniq_fid; smb_thread_t si_nbt_daemon; smb_thread_t si_tcp_daemon; @@ -1354,11 +1354,13 @@ typedef struct smb_info { #define SMB_INFO_ENCRYPT_PASSWORDS 0x80000000 #define SMB_NEW_KID() atomic_inc_64_nv(&smb_info.si_global_kid) +#define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_info.si_uniq_fid) typedef struct { + uint32_t severity; + uint32_t status; uint16_t errcls; uint16_t errcode; - DWORD status; } smb_error_t; /* |