Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
NEX-6309 Update NT status codes
Update ntstatus.h from [MS-ERREF] October 2015
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
*** 32,41 ****
--- 32,43 ----
* $Id: smb_subr.c,v 1.27.108.1 2005/06/02 00:55:39 lindak Exp $
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kmem.h>
*** 55,108 ****
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_rq.h>
#include <netsmb/smb_subr.h>
- /*
- * XXX:This conversion might not be fully MS-Compatible
- * for calculating hashes. The output length may differ
- * for some locales and needs to be handled from where
- * the call is made.
- */
- int
- smb_toupper(const char *inbuf, char *outbuf, size_t outlen)
- {
- int err = 0;
- size_t inlen, inrem, outrem;
-
- inrem = inlen = strlen(inbuf);
- outrem = outlen;
- (void) u8_textprep_str((char *)inbuf, &inrem, outbuf, &outrem,
- U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err);
- /* inrem, outrem are bytes unused, remaining */
- if (inrem) {
- SMBSDEBUG("input %d remains: %s\n", (int)inrem, inbuf);
- inlen -= inrem;
- }
- if (outrem) {
- outlen -= outrem;
- outbuf[outlen] = '\0';
- }
- if (outlen > inlen) {
- SMBSDEBUG("outlen > inlen! (%d > %d)\n",
- (int)outlen, (int)inlen);
- /* Truncate to inlen here? */
- }
-
- return (err);
- }
-
void
smb_credinit(struct smb_cred *scred, cred_t *cr)
{
/* cr arg is optional */
if (cr == NULL)
cr = ddi_get_cred();
if (is_system_labeled()) {
cr = crdup(cr);
(void) setpflags(NET_MAC_AWARE, 1, cr);
! } else {
crhold(cr);
}
scred->scr_cred = cr;
}
--- 57,79 ----
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_rq.h>
#include <netsmb/smb_subr.h>
void
smb_credinit(struct smb_cred *scred, cred_t *cr)
{
/* cr arg is optional */
if (cr == NULL)
cr = ddi_get_cred();
+ #ifdef _KERNEL
if (is_system_labeled()) {
cr = crdup(cr);
(void) setpflags(NET_MAC_AWARE, 1, cr);
! } else
! #endif
! {
crhold(cr);
}
scred->scr_cred = cr;
}
*** 113,122 ****
--- 84,101 ----
crfree(scred->scr_cred);
scred->scr_cred = NULL;
}
}
+ #ifndef _KERNEL
+ /* ARGSUSED */
+ void
+ smb_debugmsg(const char *func, char *msg)
+ {
+ }
+ #endif /* _KERNEL */
+
/*
* Helper for the SMBERROR macro, etc.
* This is also a good place for a breakpoint
* or a dtrace probe, i.e. fbt:nsmb:smb_errmsg
*/
*** 135,144 ****
--- 114,126 ----
*/
(void) vsnprintf(buf, sizeof (buf), fmt, adx);
DTRACE_PROBE2(debugmsg2,
(char *), func_name,
(char *), buf);
+ #ifndef _KERNEL
+ smb_debugmsg(func_name, buf);
+ #endif
} else {
/*
* This is one of our xxxERROR macros.
* Add a prefix to the fmt string,
* then let vcmn_err do the args.
*** 188,197 ****
--- 170,182 ----
#define ENOMEDIUM ENXIO
#endif
#ifndef ETIME
#define ETIME ETIMEDOUT
#endif
+ #ifndef EMOREDATA
+ #define EMOREDATA (0x7fff)
+ #endif
/*
* Log any un-handled NT or DOS errors we encounter.
* Make these log NOTICE in a debug build to ensure
* they get noticed during tests. In the field these
*** 217,227 ****
{NT_STATUS_ACCOUNT_EXPIRED, EACCES},
{NT_STATUS_ACCOUNT_LOCKED_OUT, EACCES},
{NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
{NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
{NT_STATUS_BAD_NETWORK_NAME, ENOENT},
! {NT_STATUS_BUFFER_TOO_SMALL, EMOREDATA},
{NT_STATUS_CANNOT_DELETE, EACCES},
{NT_STATUS_CONFLICTING_ADDRESSES, EADDRINUSE},
{NT_STATUS_CONNECTION_ABORTED, ECONNABORTED},
{NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
{NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
--- 202,214 ----
{NT_STATUS_ACCOUNT_EXPIRED, EACCES},
{NT_STATUS_ACCOUNT_LOCKED_OUT, EACCES},
{NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
{NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
{NT_STATUS_BAD_NETWORK_NAME, ENOENT},
! {NT_STATUS_BAD_NETWORK_PATH, ENOENT},
! {NT_STATUS_BUFFER_TOO_SMALL, E2BIG},
! {NT_STATUS_CANCELLED, ECANCELED},
{NT_STATUS_CANNOT_DELETE, EACCES},
{NT_STATUS_CONFLICTING_ADDRESSES, EADDRINUSE},
{NT_STATUS_CONNECTION_ABORTED, ECONNABORTED},
{NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
{NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
*** 231,317 ****
{NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
{NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
{NT_STATUS_DISK_FULL, ENOSPC},
{NT_STATUS_DLL_NOT_FOUND, ELIBACC},
{NT_STATUS_DUPLICATE_NAME, EINVAL},
{NT_STATUS_END_OF_FILE, ENODATA},
{NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
{NT_STATUS_FILE_LOCK_CONFLICT, EAGAIN},
{NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
{NT_STATUS_FLOAT_OVERFLOW, ERANGE},
{NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
{NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
! {NT_STATUS_ILL_FORMED_PASSWORD, EACCES},
{NT_STATUS_INTEGER_OVERFLOW, ERANGE},
! {NT_STATUS_INVALID_ACCOUNT_NAME, EACCES},
{NT_STATUS_INVALID_HANDLE, EBADF},
{NT_STATUS_INVALID_LEVEL, ENOTSUP},
! {NT_STATUS_INVALID_LOGON_HOURS, EACCES},
{NT_STATUS_INVALID_OWNER, EINVAL},
{NT_STATUS_INVALID_PARAMETER, EINVAL},
{NT_STATUS_INVALID_PIPE_STATE, EPIPE},
{NT_STATUS_INVALID_PRIMARY_GROUP, EINVAL},
{NT_STATUS_INVALID_WORKSTATION, EACCES},
{NT_STATUS_IN_PAGE_ERROR, EFAULT},
{NT_STATUS_IO_TIMEOUT, ETIMEDOUT},
! {NT_STATUS_IP_ADDRESS_CONFLICT1, ENOTUNIQ},
! {NT_STATUS_IP_ADDRESS_CONFLICT2, ENOTUNIQ},
{NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
{NT_STATUS_LOCK_NOT_GRANTED, EAGAIN},
! {NT_STATUS_LOGIN_TIME_RESTRICTION, EACCES},
! {NT_STATUS_LOGON_FAILURE, EACCES},
{NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
{NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
{NT_STATUS_NAME_TOO_LONG, ENAMETOOLONG},
{NT_STATUS_NETWORK_ACCESS_DENIED, EACCES},
{NT_STATUS_NETWORK_BUSY, EBUSY},
{NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
{NT_STATUS_NET_WRITE_FAULT, ECOMM},
{NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
{NT_STATUS_NONE_MAPPED, EINVAL},
{NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
{NT_STATUS_NOT_IMPLEMENTED, ENOTSUP},
{NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
{NT_STATUS_NOT_SUPPORTED, ENOTSUP},
{NT_STATUS_NO_MEDIA, ENOMEDIUM},
{NT_STATUS_NO_MEDIA_IN_DEVICE, ENOMEDIUM},
{NT_STATUS_NO_MEMORY, ENOMEM},
{NT_STATUS_NO_SUCH_DEVICE, ENODEV},
{NT_STATUS_NO_SUCH_FILE, ENOENT},
{NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
{NT_STATUS_OBJECT_NAME_INVALID, EINVAL},
{NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
{NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
{NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
{NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
! {NT_STATUS_PASSWORD_EXPIRED, EACCES},
! {NT_STATUS_PASSWORD_MUST_CHANGE, EACCES},
! {NT_STATUS_PASSWORD_RESTRICTION, EACCES},
{NT_STATUS_PATH_NOT_COVERED, ENOENT},
{NT_STATUS_PIPE_BROKEN, EPIPE},
{NT_STATUS_PIPE_BUSY, EPIPE},
{NT_STATUS_PIPE_CONNECTED, EISCONN},
{NT_STATUS_PIPE_DISCONNECTED, EPIPE},
{NT_STATUS_PIPE_NOT_AVAILABLE, EBUSY},
{NT_STATUS_PORT_CONNECTION_REFUSED, ECONNREFUSED},
{NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE},
{NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
{NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
{NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
! {NT_STATUS_RANGE_NOT_LOCKED, EIO},
{NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
{NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
{NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
{NT_STATUS_REQUEST_NOT_ACCEPTED, EACCES},
{NT_STATUS_RETRY, EAGAIN},
{NT_STATUS_SHARING_VIOLATION, EBUSY},
{NT_STATUS_TIMER_NOT_CANCELED, ETIME},
{NT_STATUS_TOO_MANY_LINKS, EMLINK},
{NT_STATUS_TOO_MANY_OPENED_FILES, EMFILE},
{NT_STATUS_UNABLE_TO_FREE_VM, EADDRINUSE},
{NT_STATUS_UNSUCCESSFUL, EINVAL},
! {NT_STATUS_WRONG_PASSWORD, EACCES},
{0, 0}
};
/*
* Table for converting NT STATUS values to DOS class/code.
--- 218,335 ----
{NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
{NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
{NT_STATUS_DISK_FULL, ENOSPC},
{NT_STATUS_DLL_NOT_FOUND, ELIBACC},
{NT_STATUS_DUPLICATE_NAME, EINVAL},
+ {NT_STATUS_EAS_NOT_SUPPORTED, ENOTSUP},
+ {NT_STATUS_EA_TOO_LARGE, E2BIG},
{NT_STATUS_END_OF_FILE, ENODATA},
+ {NT_STATUS_FILE_CLOSED, EBADF},
+ {NT_STATUS_FILE_DELETED, ENOENT},
+ {NT_STATUS_FILE_INVALID, EIO},
{NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
{NT_STATUS_FILE_LOCK_CONFLICT, EAGAIN},
+ {NT_STATUS_FILE_RENAMED, ENOENT},
{NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
{NT_STATUS_FLOAT_OVERFLOW, ERANGE},
{NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
{NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
! {NT_STATUS_ILL_FORMED_PASSWORD, EAUTH},
! {NT_STATUS_INFO_LENGTH_MISMATCH, EINVAL},
! {NT_STATUS_INSUFFICIENT_RESOURCES, EAGAIN},
! {NT_STATUS_INSUFF_SERVER_RESOURCES, EAGAIN},
{NT_STATUS_INTEGER_OVERFLOW, ERANGE},
! {NT_STATUS_INVALID_ACCOUNT_NAME, EAUTH},
! {NT_STATUS_INVALID_BUFFER_SIZE, EIO},
! {NT_STATUS_INVALID_DEVICE_REQUEST, EINVAL},
{NT_STATUS_INVALID_HANDLE, EBADF},
+ {NT_STATUS_INVALID_INFO_CLASS, EINVAL},
{NT_STATUS_INVALID_LEVEL, ENOTSUP},
! {NT_STATUS_INVALID_LOCK_SEQUENCE, EINVAL},
! {NT_STATUS_INVALID_LOGON_HOURS, EAUTH},
{NT_STATUS_INVALID_OWNER, EINVAL},
{NT_STATUS_INVALID_PARAMETER, EINVAL},
{NT_STATUS_INVALID_PIPE_STATE, EPIPE},
{NT_STATUS_INVALID_PRIMARY_GROUP, EINVAL},
{NT_STATUS_INVALID_WORKSTATION, EACCES},
{NT_STATUS_IN_PAGE_ERROR, EFAULT},
+ {NT_STATUS_IO_DEVICE_ERROR, EIO},
{NT_STATUS_IO_TIMEOUT, ETIMEDOUT},
! {NT_STATUS_IP_ADDRESS_CONFLICT1, EADDRINUSE},
! {NT_STATUS_IP_ADDRESS_CONFLICT2, EADDRINUSE},
{NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
{NT_STATUS_LOCK_NOT_GRANTED, EAGAIN},
! {NT_STATUS_LOGIN_TIME_RESTRICTION, EAUTH},
! {NT_STATUS_LOGON_FAILURE, EAUTH},
! {NT_STATUS_LOGON_TYPE_NOT_GRANTED, EAUTH},
{NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
{NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
+ {NT_STATUS_MORE_PROCESSING_REQUIRED, EINPROGRESS},
{NT_STATUS_NAME_TOO_LONG, ENAMETOOLONG},
{NT_STATUS_NETWORK_ACCESS_DENIED, EACCES},
{NT_STATUS_NETWORK_BUSY, EBUSY},
+ {NT_STATUS_NETWORK_NAME_DELETED, ENOENT},
{NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
{NT_STATUS_NET_WRITE_FAULT, ECOMM},
+ {NT_STATUS_NONEXISTENT_EA_ENTRY, ENOENT},
{NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
{NT_STATUS_NONE_MAPPED, EINVAL},
{NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
+ {NT_STATUS_NOT_FOUND, ENOENT},
{NT_STATUS_NOT_IMPLEMENTED, ENOTSUP},
+ {NT_STATUS_NOT_LOCKED, ENOLCK},
{NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
{NT_STATUS_NOT_SUPPORTED, ENOTSUP},
+ {NT_STATUS_NO_EAS_ON_FILE, ENOENT},
+ {NT_STATUS_NO_LOGON_SERVERS, EAUTH},
{NT_STATUS_NO_MEDIA, ENOMEDIUM},
{NT_STATUS_NO_MEDIA_IN_DEVICE, ENOMEDIUM},
{NT_STATUS_NO_MEMORY, ENOMEM},
{NT_STATUS_NO_SUCH_DEVICE, ENODEV},
{NT_STATUS_NO_SUCH_FILE, ENOENT},
+ {NT_STATUS_NO_SUCH_LOGON_SESSION, EAUTH},
+ {NT_STATUS_NO_SUCH_USER, EAUTH},
+ {NT_STATUS_NO_TRUST_LSA_SECRET, EAUTH},
+ {NT_STATUS_NO_TRUST_SAM_ACCOUNT, EAUTH},
{NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
{NT_STATUS_OBJECT_NAME_INVALID, EINVAL},
{NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
{NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
{NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
+ {NT_STATUS_OBJECT_PATH_SYNTAX_BAD, EINVAL},
+ {NT_STATUS_OBJECT_TYPE_MISMATCH, EBADF},
{NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
! {NT_STATUS_PASSWORD_EXPIRED, EAUTH},
! {NT_STATUS_PASSWORD_MUST_CHANGE, EAUTH},
! {NT_STATUS_PASSWORD_RESTRICTION, EAUTH},
{NT_STATUS_PATH_NOT_COVERED, ENOENT},
{NT_STATUS_PIPE_BROKEN, EPIPE},
{NT_STATUS_PIPE_BUSY, EPIPE},
{NT_STATUS_PIPE_CONNECTED, EISCONN},
{NT_STATUS_PIPE_DISCONNECTED, EPIPE},
{NT_STATUS_PIPE_NOT_AVAILABLE, EBUSY},
{NT_STATUS_PORT_CONNECTION_REFUSED, ECONNREFUSED},
+ {NT_STATUS_PORT_DISCONNECTED, EBADF},
{NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE},
{NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
{NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
{NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
! {NT_STATUS_RANGE_NOT_LOCKED, EAGAIN}, /* like F_SETLK */
{NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
{NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
{NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
{NT_STATUS_REQUEST_NOT_ACCEPTED, EACCES},
{NT_STATUS_RETRY, EAGAIN},
{NT_STATUS_SHARING_VIOLATION, EBUSY},
{NT_STATUS_TIMER_NOT_CANCELED, ETIME},
{NT_STATUS_TOO_MANY_LINKS, EMLINK},
{NT_STATUS_TOO_MANY_OPENED_FILES, EMFILE},
+ {NT_STATUS_TRUSTED_DOMAIN_FAILURE, EAUTH},
+ {NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE, EAUTH},
{NT_STATUS_UNABLE_TO_FREE_VM, EADDRINUSE},
{NT_STATUS_UNSUCCESSFUL, EINVAL},
! {NT_STATUS_WRONG_PASSWORD, EAUTH},
{0, 0}
};
/*
* Table for converting NT STATUS values to DOS class/code.
*** 591,608 ****
{ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING},
{ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE},
{ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION},
{ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE},
{ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
- {ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR},
{ERRHRD, ERRgeneral, NT_STATUS_NO_LDT},
{ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE},
{ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET},
{ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR},
{ERRDOS, ERROR_BAD_EXE_FORMAT, NT_STATUS_INVALID_IMAGE_NE_FORMAT},
--- 609,618 ----
*** 866,876 ****
--- 876,899 ----
if (nt2d->nterr == nterr)
return (smb_maperror(nt2d->dclass, nt2d->derr));
return (EIO);
}
+ uint_t
+ smb_doserr2status(int dclass, int derr)
+ {
+ const nt2doserr_t *nt2d;
+ if (dclass == 0 && derr == 0)
+ return (0);
+
+ for (nt2d = nt2doserr; nt2d->nterr; nt2d++)
+ if (nt2d->dclass == dclass && nt2d->derr == derr)
+ return (nt2d->nterr);
+ return (NT_STATUS_UNSUCCESSFUL);
+ }
+
int
smb_maperror(int eclass, int eno)
{
if (eclass == 0 && eno == 0)
return (0);
*** 994,1010 ****
smb_errmsg(unknown_err_logpri, "smb_maperror",
"Unknown DOS error %d/%d\n", eclass, eno);
return (EIO);
}
- #if defined(NOICONVSUPPORT) || defined(lint)
- extern int iconv_conv(void *handle, const char **inbuf,
- size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
- #endif
-
#define SMALL_CONV 256
/*ARGSUSED*/
int
smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
int size, int caseopt, int *lenp)
{
--- 1017,1110 ----
smb_errmsg(unknown_err_logpri, "smb_maperror",
"Unknown DOS error %d/%d\n", eclass, eno);
return (EIO);
}
#define SMALL_CONV 256
+ /*
+ * Decode an SMB OTW string (Unicode or OEM chars)
+ * converting to UTF-8 in the output buffer.
+ * outlen is in/out (max size on input)
+ * insize is the wire size (2 * chars if unicode)
+ * The output string is null terminated.
+ * Output length does not include the null.
+ */
+ int
+ smb_get_dstring(struct mdchain *mdc, struct smb_vc *vcp,
+ char *outbuf, size_t *outlen, int insize)
+ {
+ uint16_t convbuf[SMALL_CONV];
+ uint16_t *cbuf;
+ size_t cbufalloc, inlen, outsize;
+ int error;
+
+ if (insize <= 0)
+ return (0);
+ /* Note: inlen is UTF-16 symbols. */
+ inlen = insize / 2;
+
+ if (*outlen < 2)
+ return (EINVAL);
+ outsize = *outlen - 1; /* room for null */
+
+ /*
+ * Get a buffer for the conversion and fill it.
+ * Use stack buffer if the string is
+ * small enough, else allocate.
+ */
+ if (insize < sizeof (convbuf)) {
+ cbufalloc = 0;
+ cbuf = convbuf;
+ } else {
+ cbufalloc = insize + 2;
+ cbuf = kmem_alloc(cbufalloc, KM_SLEEP);
+ }
+ error = md_get_mem(mdc, cbuf, insize, MB_MSYSTEM);
+ if (error != 0)
+ goto out;
+ cbuf[inlen] = 0;
+
+ /*
+ * Handle the easy case (non-unicode).
+ * XXX: Technically, we should convert
+ * the string to OEM codeset first...
+ * Modern servers all use Unicode, so
+ * this is good enough.
+ */
+ if (SMB_UNICODE_STRINGS(vcp) == 0) {
+ *outlen = strlcpy(outbuf, (char *)cbuf, outsize);
+ if (*outlen > outsize) {
+ *outlen = outsize;
+ error = E2BIG;
+ }
+ } else {
+ /*
+ * Convert from UTF-16 to UTF-8
+ */
+ error = uconv_u16tou8(cbuf, &inlen,
+ (uchar_t *)outbuf, outlen,
+ UCONV_IN_LITTLE_ENDIAN);
+ if (error == 0) {
+ outbuf[*outlen] = '\0';
+ }
+ }
+
+ ASSERT(*outlen == strlen(outbuf));
+
+ out:
+ if (cbufalloc != 0)
+ kmem_free(cbuf, cbufalloc);
+
+ return (error);
+ }
+
+ /*
+ * It's surprising that this function does utf8-ucs2 conversion.
+ * One would expect only smb_put_dstring to do that.
+ * Fixing that will require changing a bunch of callers. XXX
+ */
/*ARGSUSED*/
int
smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
int size, int caseopt, int *lenp)
{
*** 1077,1082 ****
--- 1177,1309 ----
error = smb_put_dmem(mbp, vcp, src, len, caseopt, NULL);
if (error)
return (error);
return (error);
+ }
+ int
+ smb_smb_ntcreate(struct smb_share *ssp, struct mbchain *name_mb,
+ uint32_t crflag, uint32_t req_acc, uint32_t efa, uint32_t sh_acc,
+ uint32_t disp, uint32_t createopt, uint32_t impersonate,
+ struct smb_cred *scrp, smb_fh_t *fhp,
+ uint32_t *cr_act_p, struct smbfattr *fap)
+ {
+ int err;
+
+ if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
+ err = smb2_smb_ntcreate(ssp, name_mb, NULL, NULL,
+ crflag, req_acc, efa, sh_acc, disp, createopt,
+ impersonate, scrp, &fhp->fh_fid2, cr_act_p, fap);
+ } else {
+ err = smb1_smb_ntcreate(ssp, name_mb, crflag, req_acc,
+ efa, sh_acc, disp, createopt, impersonate, scrp,
+ &fhp->fh_fid1, cr_act_p, fap);
+ }
+ return (err);
+ }
+
+ int
+ smb_smb_close(struct smb_share *ssp, smb_fh_t *fhp,
+ struct smb_cred *scrp)
+ {
+ int err;
+
+ if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
+ err = smb2_smb_close(ssp, &fhp->fh_fid2, scrp);
+ } else {
+ err = smb1_smb_close(ssp, fhp->fh_fid1, NULL, scrp);
+ }
+
+ return (err);
+ }
+
+ /*
+ * Largest size to use with LARGE_READ/LARGE_WRITE.
+ * Specs say up to 64k data bytes, but Windows traffic
+ * uses 60k... no doubt for some good reason.
+ * (Probably to keep 4k block alignment.)
+ */
+ uint32_t smb1_large_io_max = (60*1024);
+
+ /*
+ * Common function for read/write with UIO.
+ * Called by netsmb smb_usr_rw,
+ * smbfs_readvnode, smbfs_writevnode
+ */
+ int
+ smb_rwuio(smb_fh_t *fhp, uio_rw_t rw,
+ uio_t *uiop, smb_cred_t *scred, int timo)
+ {
+ struct smb_share *ssp = FHTOSS(fhp);
+ struct smb_vc *vcp = SSTOVC(ssp);
+ ssize_t save_resid;
+ uint32_t len, rlen, maxlen;
+ int error = 0;
+ int (*iofun)(smb_fh_t *, uint32_t *,
+ uio_t *, smb_cred_t *, int);
+
+ /* After reconnect, the fid is invalid. */
+ if (fhp->fh_vcgenid != ssp->ss_vcgenid)
+ return (ESTALE);
+
+ if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
+ if (rw == UIO_READ) {
+ iofun = smb2_smb_read;
+ maxlen = vcp->vc_sopt.sv2_maxread;
+ } else { /* UIO_WRITE */
+ iofun = smb2_smb_write;
+ maxlen = vcp->vc_sopt.sv2_maxwrite;
+ }
+ } else {
+ /*
+ * Using NT LM 0.12, so readx, writex.
+ * Make sure we can represent the offset.
+ */
+ if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
+ (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
+ return (EFBIG);
+
+ if (rw == UIO_READ) {
+ iofun = smb_smb_readx;
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
+ maxlen = smb1_large_io_max;
+ else
+ maxlen = vcp->vc_rxmax;
+ } else { /* UIO_WRITE */
+ iofun = smb_smb_writex;
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
+ maxlen = smb1_large_io_max;
+ else
+ maxlen = vcp->vc_wxmax;
+ }
+ }
+
+ save_resid = uiop->uio_resid;
+ while (uiop->uio_resid > 0) {
+ /* Lint: uio_resid may be 64-bits */
+ rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
+ error = (*iofun)(fhp, &rlen, uiop, scred, timo);
+
+ /*
+ * Note: the iofun called uio_update, so
+ * not doing that here as one might expect.
+ *
+ * Quit the loop either on error, or if we
+ * transferred less then requested.
+ */
+ if (error || (rlen < len))
+ break;
+
+ timo = 0; /* only first I/O should wait */
+ }
+ if (error && (save_resid != uiop->uio_resid)) {
+ /*
+ * Stopped on an error after having
+ * successfully transferred data.
+ * Suppress this error.
+ */
+ SMBSDEBUG("error %d suppressed\n", error);
+ error = 0;
+ }
+
+ return (error);
}