#include "smb.h"
#include "lanahelper.h"
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
+
/* These characters are illegal in Windows filenames */
static char *illegalChars = "\\/:*?\"<>|";
osi_rwlock_t smb_globalLock;
osi_rwlock_t smb_rctLock;
osi_mutex_t smb_ListenerLock;
+osi_mutex_t smb_StartedLock;
-char smb_LANadapter = -1;
+unsigned char smb_LANadapter = LANA_INVALID;
unsigned char smb_sharename[NCBNAMSZ+1] = {0};
+int smb_LanAdapterChangeDetected = 0;
+afs_uint32 smb_AsyncStore = 1;
+afs_uint32 smb_AsyncStoreSize = CM_CONFIGDEFAULT_ASYNCSTORESIZE;
BOOL isGateway = FALSE;
smb_packet_t *smb_packetFreeListp;
smb_ncb_t *smb_ncbFreeListp;
-int smb_NumServerThreads;
+afs_uint32 smb_NumServerThreads;
-int numNCBs, numSessions, numVCs;
+afs_uint32 numNCBs, numSessions, numVCs;
int smb_maxVCPerServer;
int smb_maxMpxRequests;
EVENT_HANDLE **NCBreturns;
EVENT_HANDLE **NCBShutdown;
EVENT_HANDLE *smb_ServerShutdown;
+EVENT_HANDLE ListenerShutdown[256];
DWORD NCBsessions[NCB_MAX];
NCB *NCBs[NCB_MAX];
struct smb_packet *bufs[NCB_MAX];
int lanas[SESSION_MAX];
BOOL dead_sessions[SESSION_MAX];
LANA_ENUM lana_list;
-
/* for raw I/O */
osi_mutex_t smb_RawBufLock;
char *smb_RawBufs;
/* hide dot files? */
int smb_hideDotFiles;
+/* Negotiate Unicode support? */
+LONG smb_UseUnicode;
+
/* global state about V3 protocols */
int smb_useV3; /* try to negotiate V3 */
/* forward decl */
void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
NCB *ncbp, raw_write_cont_t *rwcp);
-int smb_NetbiosInit(void);
+int smb_NetbiosInit(int);
#ifdef LOG_PACKET
void smb_LogPacket(smb_packet_t *packet);
time_t now = osi_Time();
/* Give one priority boost for each 15 seconds */
- SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
+ SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
}
}
{
smb_vc_t *vcp;
- lock_ObtainWrite(&smb_globalLock); /* for numVCs */
+ lock_ObtainWrite(&smb_globalLock); /* for numVCs */
lock_ObtainWrite(&smb_rctLock);
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
if (vcp->magic != SMB_VC_MAGIC)
}
}
lock_ReleaseWrite(&smb_rctLock);
- lock_ReleaseWrite(&smb_globalLock);
+ lock_ReleaseWrite(&smb_globalLock);
return vcp;
}
vcp->refCount--;
if (vcp->refCount == 0) {
- if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
- /* remove VCP from smb_deadVCsp */
- for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
- if (*vcpp == vcp) {
- *vcpp = vcp->nextp;
- break;
- }
- }
- lock_FinalizeMutex(&vcp->mx);
- memset(vcp,0,sizeof(smb_vc_t));
- free(vcp);
- } else {
- for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
- if (avcp == vcp)
- break;
- }
- osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
- avcp?"not ":"",vcp, vcp->refCount);
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ /* remove VCP from smb_deadVCsp */
+ for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+ if (*vcpp == vcp) {
+ *vcpp = vcp->nextp;
+ break;
+ }
+ }
+ lock_FinalizeMutex(&vcp->mx);
+ memset(vcp,0,sizeof(smb_vc_t));
+ free(vcp);
+ } else {
+ for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
+ if (avcp == vcp)
+ break;
+ }
+ osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
+ avcp?"not ":"",vcp, vcp->refCount);
#ifdef DEBUG
- GenerateMiniDump(NULL);
+ GenerateMiniDump(NULL);
#endif
- /* This is a wrong. However, I suspect that there is an undercount
- * and I don't want to release 1.4.1 in a state that will allow
- * smb_vc_t objects to be deallocated while still in the
- * smb_allVCsp list. The list is supposed to keep a reference
- * to the smb_vc_t. Put it back.
- */
- vcp->refCount++;
- }
+ /* This is a wrong. However, I suspect that there is an undercount
+ * and I don't want to release 1.4.1 in a state that will allow
+ * smb_vc_t objects to be deallocated while still in the
+ * smb_allVCsp list. The list is supposed to keep a reference
+ * to the smb_vc_t. Put it back.
+ */
+ vcp->refCount++;
+ }
}
}
for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
- if (fidpIter->delete)
+ if (fidpIter->deleteOk)
continue;
fid = fidpIter->fid;
for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
tidpNext = tidpIter->nextp;
- if (tidpIter->delete)
+ if (tidpIter->deleteOk)
continue;
- tidpIter->delete = 1;
+ tidpIter->deleteOk = 1;
tid = tidpIter->tid;
osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
smb_HoldTIDNoLock(tidpIter);
- lock_ReleaseWrite(&smb_rctLock);
-
- smb_ReleaseTID(tidpIter);
-
- lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseTID(tidpIter, TRUE);
tidpNext = vcp->tidsp;
}
for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
uidpNext = uidpIter->nextp;
- if (uidpIter->delete)
+ if (uidpIter->deleteOk)
continue;
- uidpIter->delete = 1;
+ uidpIter->deleteOk = 1;
/* do not add an additional reference count for the smb_user_t
* as the smb_vc_t already is holding a reference */
lock_ObtainWrite(&smb_rctLock);
retry:
for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
- if (tidp->refCount == 0 && tidp->delete) {
+ if (tidp->refCount == 0 && tidp->deleteOk) {
tidp->refCount++;
- lock_ReleaseWrite(&smb_rctLock);
- smb_ReleaseTID(tidp);
- lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseTID(tidp, TRUE);
goto retry;
}
tidp->refCount++;
}
-void smb_ReleaseTID(smb_tid_t *tidp)
+void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
{
smb_tid_t *tp;
smb_tid_t **ltpp;
cm_user_t *userp;
userp = NULL;
- lock_ObtainWrite(&smb_rctLock);
+ if (!locked)
+ lock_ObtainWrite(&smb_rctLock);
osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
- if (tidp->refCount == 0 && (tidp->delete)) {
+ if (tidp->refCount == 0 && (tidp->deleteOk)) {
ltpp = &tidp->vcp->tidsp;
for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
if (tp == tidp)
smb_ReleaseVCNoLock(tidp->vcp);
tidp->vcp = NULL;
}
- lock_ReleaseWrite(&smb_rctLock);
+ if (!locked)
+ lock_ReleaseWrite(&smb_rctLock);
if (userp)
cm_ReleaseUser(userp);
}
lock_ObtainWrite(&smb_rctLock);
for(unp = usernamesp; unp; unp = unp->nextp) {
- if (stricmp(unp->name, usern) == 0 &&
- stricmp(unp->machine, machine) == 0) {
+ if (cm_stricmp_utf8(unp->name, usern) == 0 &&
+ cm_stricmp_utf8(unp->machine, machine) == 0) {
unp->refCount++;
break;
}
for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
if (!uidp->unp)
continue;
- if (stricmp(uidp->unp->name, usern) == 0) {
+ if (cm_stricmp_utf8(uidp->unp->name, usern) == 0) {
uidp->refCount++;
osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
free(unp);
}
lock_ReleaseWrite(&smb_rctLock);
-
- if (userp) {
+ if (userp)
cm_ReleaseUser(userp);
- }
}
void smb_HoldUIDNoLock(smb_user_t *uidp)
/* tidp->pathname would be NULL, but that's fine */
}
*treepath = tidp->pathname;
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
}
return code;
}
retry:
for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
- if (fidp->refCount == 0 && fidp->delete) {
+ if (fidp->refCount == 0 && fidp->deleteOk) {
fidp->refCount++;
lock_ReleaseWrite(&smb_rctLock);
smb_ReleaseFID(fidp);
lock_ObtainMutex(&fidp->mx);
lock_ObtainWrite(&smb_rctLock);
osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
- if (fidp->refCount == 0 && (fidp->delete)) {
+ if (fidp->refCount == 0 && (fidp->deleteOk)) {
vcp = fidp->vcp;
fidp->vcp = NULL;
scp = fidp->scp; /* release after lock is released */
if (scp) {
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
fidp->scp = NULL;
}
char *cursor;
for (cursor = str1; *cursor; cursor++)
- if (stricmp(cursor, str2) == 0)
+ if (cm_stricmp_utf8(cursor, str2) == 0)
return cursor;
return NULL;
{
int matchType = 0;
smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
- if (!strnicmp(dep->name, vrock->shareName, 12)) {
- if(!stricmp(dep->name, vrock->shareName))
+ char normName[MAX_PATH];
+
+ cm_NormalizeUtf8String(dep->name, -1, normName, sizeof(normName)/sizeof(char));
+
+ if (!strnicmp(normName, vrock->shareName, 12)) {
+ if(!cm_stricmp_utf8(normName, vrock->shareName))
matchType = SMB_FINDSHARE_EXACT_MATCH;
else
matchType = SMB_FINDSHARE_PARTIAL_MATCH;
if(vrock->match) free(vrock->match);
- vrock->match = strdup(dep->name);
+ vrock->match = strdup(normName);
vrock->matchType = matchType;
if(matchType == SMB_FINDSHARE_EXACT_MATCH)
RegCloseKey (parmKey);
}
- if (allSubmount && _stricmp(shareName, "all") == 0) {
+ if (allSubmount && cm_stricmp_utf8N(shareName, "all") == 0) {
*pathNamep = NULL;
return 1;
}
/* In case, the all share is disabled we need to still be able
* to handle ioctl requests
*/
- if (_stricmp(shareName, "ioctl$") == 0) {
+ if (cm_stricmp_utf8N(shareName, "ioctl$") == 0) {
*pathNamep = strdup("/.__ioctl__");
return 1;
}
- if (_stricmp(shareName, "IPC$") == 0 ||
- _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
- _stricmp(shareName, "DESKTOP.INI") == 0
+ if (cm_stricmp_utf8N(shareName, "IPC$") == 0 ||
+ cm_stricmp_utf8N(shareName, "srvsvc") == 0 ||
+ cm_stricmp_utf8N(shareName, "wkssvc") == 0 ||
+ cm_stricmp_utf8N(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
+ cm_stricmp_utf8N(shareName, "DESKTOP.INI") == 0
) {
*pathNamep = NULL;
return 0;
snprintf(pathstr, sizeof(pathstr)/sizeof(char),
"/" CM_PREFIX_VOL "%s", shareName);
pathstr[sizeof(pathstr)/sizeof(char) - 1] = '\0';
- len = strlen(pathstr) + 1;
+ len = (DWORD)(strlen(pathstr) + 1);
*pathNamep = malloc(len);
if (*pathNamep) {
len = sizeof(policy);
if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
len == 0) {
- retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
+ retval = cm_stricmp_utf8N("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
}
- else if (stricmp(policy, "documents") == 0)
+ else if (cm_stricmp_utf8N(policy, "documents") == 0)
{
retval = CSC_POLICY_DOCUMENTS;
}
- else if (stricmp(policy, "programs") == 0)
+ else if (cm_stricmp_utf8N(policy, "programs") == 0)
{
retval = CSC_POLICY_PROGRAMS;
}
- else if (stricmp(policy, "disable") == 0)
+ else if (cm_stricmp_utf8N(policy, "disable") == 0)
{
retval = CSC_POLICY_DISABLE;
}
dsp->cookie, dsp, dsp->scp);
dsp->flags |= SMB_DIRSEARCH_DELETE;
if (dsp->scp != NULL) {
- lock_ObtainMutex(&dsp->scp->mx);
+ lock_ObtainWrite(&dsp->scp->rw);
if (dsp->flags & SMB_DIRSEARCH_BULKST) {
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->scp->bulkStatProgress = hzero;
}
- lock_ReleaseMutex(&dsp->scp->mx);
+ lock_ReleaseWrite(&dsp->scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
lock_ReleaseWrite(&smb_globalLock);
smb_packetFreeListp = tbp->nextp;
lock_ReleaseWrite(&smb_globalLock);
if (!tbp) {
- tbp = calloc(65540,1);
+ tbp = calloc(sizeof(*tbp),1);
tbp->magic = SMB_PACKETMAGIC;
tbp->ncbp = NULL;
tbp->vcp = NULL;
tbp->ncb_length = 0;
tbp->flags = 0;
tbp->spacep = NULL;
-
+ tbp->stringsp = NULL;
}
osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
tbp = GetPacket();
memcpy(tbp, pkt, sizeof(smb_packet_t));
tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+ tbp->stringsp = NULL;
if (tbp->vcp)
smb_HoldVC(tbp->vcp);
return tbp;
return ncbp;
}
+static void FreeSMBStrings(smb_packet_t * pkt)
+{
+ cm_space_t * s;
+ cm_space_t * ns;
+
+ for (s = pkt->stringsp; s; s = ns) {
+ ns = s->nextp;
+ cm_FreeSpace(s);
+ }
+ pkt->stringsp = NULL;
+}
+
void smb_FreePacket(smb_packet_t *tbp)
{
smb_vc_t * vcp = NULL;
tbp->oddByte = 0;
tbp->ncb_length = 0;
tbp->flags = 0;
+ FreeSMBStrings(tbp);
lock_ReleaseWrite(&smb_globalLock);
if (vcp)
*parmDatap++ = parmValue & 0xff;
}
+
+
void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp)
{
char *lastSlashp;
}
}
-unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
+unsigned char *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
+ char **chainpp, int flags)
{
+ size_t cb;
+
if (*inp++ != 0x4)
return NULL;
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ cb = sizeof(pktp->data) - (inp - pktp->data);
+ if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ cb = sizeof(pktp->data);
+ }
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+unsigned char *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
+ char ** chainpp, int flags)
+{
+ size_t cb;
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ cb = sizeof(pktp->data) - (inp - pktp->data);
+ if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ cb = sizeof(pktp->data);
+ }
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+unsigned char *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
+ size_t cb, char ** chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+unsigned char *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp,
+ size_t cch, char ** chainpp, int flags)
+{
+ size_t cb = cch;
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+ else
+ cb = cch * sizeof(wchar_t);
+#endif
+
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+unsigned char *smb_ParseStringBuf(const unsigned char * bufbase,
+ cm_space_t ** stringspp,
+ unsigned char *inp, size_t *pcb_max,
+ char **chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+ if (!(flags & SMB_STRF_FORCEASCII)) {
+ size_t cch_src;
+ int cb_dest;
+ cm_space_t * spacep;
+ int null_terms = 0;
+
+ if (bufbase && ((inp - bufbase) % 2) != 0) {
+ inp++; /* unicode strings are always word aligned */
+ }
+
+ if (*pcb_max > 0) {
+ if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t),
+ &cch_src))) {
+ cch_src = *pcb_max / sizeof(wchar_t);
+ *pcb_max = 0;
+ null_terms = 0;
+ } else {
+ *pcb_max -= (cch_src + 1) * sizeof(wchar_t);
+ null_terms = 1;
+ }
+ } else {
+ cch_src = 0;
+ }
+
+ spacep = cm_GetSpace();
+ spacep->nextp = *stringspp;
+ *stringspp = spacep;
+
+ if (cch_src == 0) {
+ if (chainpp) {
+ *chainpp = inp + sizeof(wchar_t);
+ }
+
+ spacep->data[0] = '\0';
+ return spacep->data;
+ }
+
+ cb_dest = cm_NormalizeUtf16StringToUtf8((const wchar_t *) inp, cch_src,
+ spacep->data, sizeof(spacep->data));
+ if (cb_dest == 0) {
+ *stringspp = spacep->nextp;
+ cm_FreeSpace(spacep);
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ return NULL;
+ }
+
+ if (chainpp)
+ *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t);
+
+ if (cb_dest == 0) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ } else if (spacep->data[cb_dest - 1] != 0) {
+ spacep->data[cb_dest++] = 0;
+ }
+
+ return spacep->data;
+
+ } else {
+#endif
+ /* Not using Unicode */
if (chainpp) {
- *chainpp = inp + strlen(inp) + 1; /* skip over null-terminated string */
+ *chainpp = inp + strlen(inp) + 1;
}
+ if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames)
+ OemToChar(inp, inp);
return inp;
+#ifdef SMB_UNICODE
+ }
+#endif
+}
+
+unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
+ unsigned char * str,
+ size_t * plen, int flags)
+{
+ size_t buffersize;
+ int align = 0;
+
+ if (outp == NULL) {
+ /* we are only calculating the required size */
+#ifdef SMB_UNICODE
+
+ if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+ int nchars;
+
+ nchars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ str, -1, NULL, 0);
+ if (nchars == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
+
+ if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames)
+ nchars = MultiByteToWideChar(1252 /* ANSI - Latin1 */,
+ 0, str, -1, NULL, 0);
+ else
+ nchars = MultiByteToWideChar(CP_OEMCP,
+ 0, str, -1, NULL, 0);
+ }
+
+ if (nchars == 0) {
+ osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
+ osi_LogSaveString(smb_logp, str),
+ GetLastError());
+ if (plen)
+ *plen = 0;
+ return NULL;
+ }
+
+ if (plen)
+ *plen = sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1 : nchars);
+
+ return (unsigned char *) 1; /* return TRUE if we are using unicode */
+ }
+ else
+#endif
+ {
+ /* Storing ANSI */
+ size_t len;
+
+ len = strlen(str);
+ if (plen)
+ *plen = ((flags & SMB_STRF_IGNORENULL)? len: len+1);
+
+ return NULL;
+ }
+ }
+
+ /* Number of bytes left in the buffer. */
+ if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
+ align = ((outp - pktp->data) % 2);
+ buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
+ } else {
+ align = (((size_t) outp) % 2);
+ buffersize = sizeof(pktp->data);
+ }
+
+#ifdef SMB_UNICODE
+
+ if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+ int nchars;
+
+ if (align)
+ *outp++ = '\0';
+
+ if (*str == '\0') {
+
+ if (buffersize < sizeof(wchar_t))
+ return NULL;
+
+ *((wchar_t *) outp) = L'\0';
+ if (plen && !(flags & SMB_STRF_IGNORENULL))
+ *plen += sizeof(wchar_t);
+ return outp + sizeof(wchar_t);
+ }
+
+ nchars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ str, -1, (wchar_t *) outp, buffersize);
+ if (nchars == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
+
+ /* If we failed to translate the string from UTF-8 to
+ UTF-16, then chances are the string wasn't UTF-8 to
+ begin with. If StoreAnsiFileNames is set and this is
+ possibly an ANSI file name, we try assuming that the
+ source name is in ANSI. otherwise we try OEM. */
+
+ if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames)
+ nchars = MultiByteToWideChar(1252 /* ANSI - Latin1 */,
+ 0, str, -1, (wchar_t *) outp, buffersize);
+ else
+ nchars = MultiByteToWideChar(CP_OEMCP,
+ 0, str, -1, (wchar_t *) outp, buffersize);
+ }
+
+ if (nchars == 0) {
+ /* Both 1252 and OEM should translate to Unicode without a
+ complaint. This is something else. */
+ osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
+ osi_LogSaveString(smb_logp, str),
+ GetLastError());
+ return NULL;
+ }
+
+ if (plen)
+ *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1: nchars);
+
+ return outp + sizeof(wchar_t) * nchars;
+ }
+ else
+#endif
+ {
+ /* Storing ANSI */
+ size_t len;
+
+ len = strlen(str); len++;
+ if (len > buffersize)
+ return NULL;
+
+ strcpy(outp, str);
+ if (plen)
+ *plen += ((flags & SMB_STRF_IGNORENULL)? len - 1: len);
+
+ return outp + len;
+ }
}
unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
return inp;
}
+unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
+{
+ int tlen;
+
+ if (*inp++ != 0x1) return NULL;
+ tlen = inp[0] + (inp[1]<<8);
+ inp += 2; /* skip length field */
+
+ if (chainpp) {
+ *chainpp = inp + tlen;
+ }
+
+ if (lengthp) *lengthp = tlen;
+
+ return inp;
+}
+
/* format a packet as a response */
void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
{
outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
#endif
outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
+#ifdef SMB_UNICODE
+ if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
+ outp->flg2 |= SMB_FLAGS2_UNICODE;
+#endif
/* copy fields in generic packet area */
op->wctp = &outp->wct;
NTStatus = 0xC09820FBL; /* SMB use standard */
}
else if (code == CM_ERROR_QUOTA) {
-#ifdef COMMENT
NTStatus = 0xC0000044L; /* Quota exceeded */
-#else
- NTStatus = 0xC000007FL; /* Disk full */
-#endif
}
else if (code == CM_ERROR_SPACE) {
NTStatus = 0xC000007FL; /* Disk full */
else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
NTStatus = 0xC00000BEL; /* Bad Network Path */
}
- else if (code == RXKADUNKNOWNKEY) {
- NTStatus = 0xC0000322L; /* Bad Kerberos key */
+ else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+ NTStatus = 0xC0000322L; /* No Kerberos key */
}
else if (code == CM_ERROR_BAD_LEVEL) {
NTStatus = 0xC0000148L; /* Invalid Level */
+ }
+ else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+ NTStatus = 0xC000007EL; /* Range Not Locked */
+ }
+ else if (code == CM_ERROR_NOSUCHDEVICE) {
+ NTStatus = 0xC000000EL; /* No Such Device */
+ }
+ else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+ NTStatus = 0xC0000055L; /* Lock Not Granted */
} else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
return CM_ERROR_BADOP;
}
+/* SMB_COM_ECHO */
long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short EchoCount, i;
return 0;
}
+/* SMB_COM_READ_RAW */
long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
osi_hyper_t offset;
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp = NULL;
NCB *ncbp;
}
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
{
LARGE_INTEGER LOffset, LLength;
cm_key_t key;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
if (code) {
goto send1a;
lock_ReleaseMutex(&smb_RawBufLock);
}
+ lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return rc;
}
return 0;
}
+/* SMB_COM_NEGOTIATE */
long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *namep;
* and NT Find *
* and NT SMB's *
* and raw mode
- * and DFS */
+ * and DFS
+ * and Unicode */
caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
if ( smb_authType == SMB_AUTH_EXTENDED )
caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
+#ifdef SMB_UNICODE
+ if ( smb_UseUnicode ) {
+ caps |= NTNEGOTIATE_CAPABILITY_UNICODE;
+ }
+#endif
+
smb_SetSMBParmLong(outp, 9, caps);
time(&unixTime);
smb_SearchTimeFromUnixTime(&dosTime, unixTime);
now = osi_Time();
lock_ObtainWrite(&smb_rctLock);
for ( unpp=&usernamesp; *unpp; ) {
- int delete = 0;
+ int deleteOk = 0;
smb_username_t *unp;
lock_ObtainMutex(&(*unpp)->mx);
;
else if (!smb_LogoffTokenTransfer ||
((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
- delete = 1;
+ deleteOk = 1;
lock_ReleaseMutex(&(*unpp)->mx);
- if (delete) {
+ if (deleteOk) {
cm_user_t * userp;
unp = *unpp;
free(unp->name);
free(unp->machine);
free(unp);
- if (userp) {
- lock_ReleaseWrite(&smb_rctLock);
+ if (userp)
cm_ReleaseUser(userp);
- lock_ObtainWrite(&smb_rctLock);
- }
} else {
unpp = &(*unpp)->nextp;
}
if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
continue;
+ if (wl->state == SMB_WAITINGLOCKSTATE_CANCELLED) {
+ code = CM_ERROR_LOCK_NOT_GRANTED;
+ break;
+ }
+
osi_assertx(wl->state != SMB_WAITINGLOCKSTATE_ERROR, "!SMB_WAITINGLOCKSTATE_ERROR");
/* wl->state is either _DONE or _WAITING. _ERROR
if (code == CM_ERROR_WOULDBLOCK) {
/* no progress */
- if (wlRequest->timeRemaining != 0xffffffff
- && (wlRequest->timeRemaining -= 1000) < 0)
+ if (wlRequest->msTimeout != 0xffffffff
+ && ((osi_Time() - wlRequest->start_t) * 1000 > wlRequest->msTimeout))
goto endWait;
continue;
cm_InitReq(&req);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
for (wl = wlRequest->locks; wl; wl = wlNext) {
wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
-
- cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
- wl->LLength, wl->key, NULL, &req);
+
+ if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
+ cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
+ wl->LLength, wl->key, NULL, &req);
osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
free(wl);
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
} else {
return 0;
}
+/* SMB_COM_TREE_CONNECT */
long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
{
smb_tid_t *tidp;
int shareFound;
char *tp;
char *pathp;
- char *passwordp;
cm_user_t *userp;
osi_Log0(smb_logp, "SMB receive tree connect");
/* parse input parameters */
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
- passwordp = smb_ParseASCIIBlock(tp, &tp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
tp = strrchr(pathp, '\\');
if (!tp)
return CM_ERROR_BADSMB;
if (uidp)
smb_ReleaseUID(uidp);
if (!shareFound) {
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
return CM_ERROR_BADSHARENAME;
}
lock_ObtainMutex(&tidp->mx);
tidp->userp = userp;
tidp->pathname = sharePath;
lock_ReleaseMutex(&tidp->mx);
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
smb_SetSMBParm(rsp, 1, newTid);
return 0;
}
-unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
-{
- int tlen;
-
- if (*inp++ != 0x1) return NULL;
- tlen = inp[0] + (inp[1]<<8);
- inp += 2; /* skip length field */
-
- if (chainpp) {
- *chainpp = inp + tlen;
- }
-
- if (lengthp) *lengthp = tlen;
-
- return inp;
-}
-
/* set maskp to the mask part of the incoming path.
* Mask is 11 bytes long (8.3 with the dot elided).
* Returns true if succeeds with a valid name, otherwise it does
return pathp; /* no slash, return the entire path */
}
+/* SMB_COM_SEARCH for a volume label
+
+ (This is called from smb_ReceiveCoreSearchDir() and not an actual
+ dispatch function.) */
long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned char *pathp;
/* pull pathname and stat block out of request */
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
+ pathp = smb_ParseASCIIBlock(inp, tp, (char **) &tp,
+ SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
osi_assertx(pathp != NULL, "null path");
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
osi_assertx(statBlockp != NULL, "null statBlock");
if (statLen == 0) {
*tp++ = 0;
*tp++ = 0;
+ /* The filename is a UCHAR buffer that is ASCII even if Unicode
+ was negotiated. */
+
/* finally, null-terminated 8.3 pathname, which we set to AFS */
memset(tp, ' ', 13);
strcpy(tp, "AFS");
*dptr++ = SMB_ATTR_HIDDEN;
continue;
}
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
*dptr++ = SMB_ATTR_HIDDEN;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ConvertWToR(&scp->rw);
attr = smb_Attributes(scp);
/* check hidden attribute (the flag is only ON when dot file hiding is on ) */
if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
/* copy out file length */
*((u_long *)dptr) = scp->length.LowPart;
dptr += 4;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
cm_ReleaseSCache(scp);
}
return code;
}
+/* SMB_COM_SEARCH */
long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
int attribute;
caseFold = CM_FLAG_CASEFOLD;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp,
+ SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
/* bail out if request looks bad */
* now.
*/
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
&& LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
dsp->flags |= SMB_DIRSEARCH_BULKST;
dsp->scp->bulkStatProgress = hzero;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
}
}
lock_ReleaseMutex(&dsp->mx);
smb_SetSMBParm(outp, 0, 0);
/* get the directory size */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_DeleteDirSearch(dsp);
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
- lock_ObtainRead(&scp->bufCreateLock);
+ lock_ReleaseWrite(&scp->rw);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
lock_ObtainMutex(&dsp->mx);
/* now, if we're doing a star match, do bulk fetching of all of
*/
if (starPattern) {
smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
LargeIntegerGreaterThanOrEqualTo(thyper,
scp->bulkStatProgress)) {
code = cm_TryBulkStat(scp, &thyper, userp, &req);
}
} else {
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
if (code) {
if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* no directories */
{
/* We have already done the cm_TryBulkStat above */
- fid.cell = scp->fid.cell;
- fid.volume = scp->fid.volume;
- fid.vnode = ntohl(dep->fid.vnode);
- fid.unique = ntohl(dep->fid.unique);
+ cm_SetFid(&fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
fileType = cm_FindFileType(&fid);
osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
"has filetype %d", osi_LogSaveString(smb_logp, dep->name),
curPatchp = malloc(sizeof(*curPatchp));
osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
curPatchp->dptr = op;
- curPatchp->fid.cell = scp->fid.cell;
- curPatchp->fid.volume = scp->fid.volume;
- curPatchp->fid.vnode = ntohl(dep->fid.vnode);
- curPatchp->fid.unique = ntohl(dep->fid.unique);
+ cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
/* do hidden attribute here since name won't be around when applying
* dir list patches
strncpy(op, actualName, 13);
if (smb_StoreAnsiFilenames)
CharToOem(op, op);
+ /* This is a UCHAR field, which is ASCII even if Unicode
+ is negotiated. */
/* Uppercase if requested by client */
if (!KNOWS_LONG_NAMES(inp))
} /* while copying data for dir listing */
/* release the mutex */
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp) {
buf_Release(bufferp);
bufferp = NULL;
return code;
}
+
/* verify that this is a valid path to a directory. I don't know why they
* don't use the get file attributes call.
+ *
+ * SMB_COM_CHECK_DIRECTORY
*/
long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
cm_InitReq(&req);
pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADFD;
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive check path %s",
osi_LogSaveString(smb_logp, pathp));
#endif /* DFS_SUPPORT */
/* now lock the vnode with a callback; returns with newScp locked */
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
if (code != CM_ERROR_NOACCESS) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
if (!(attrs & SMB_ATTR_DIRECTORY))
code = CM_ERROR_NOTDIR;
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
}
+/* SMB_COM_SET_INFORMATION */
long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp;
dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADSMB;
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
dosTime, attribute);
* need the current status to determine what the new status is, in some
* cases.
*/
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
/* Check for RO volume */
if (newScp->flags & CM_SCACHEFLAG_RO) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return CM_ERROR_READONLY;
attr.unixModeBits = newScp->unixModeBits | 0222;
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
}
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
/* now call setattr */
if (attr.mask)
return code;
}
+
long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp;
cm_InitReq(&req);
pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADSMB;
if (*pathp == 0) /* null path */
pathp = "\\";
- else
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
osi_LogSaveString(smb_logp, pathp));
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
- if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
+ if (lastComp && cm_stricmp_utf8N(lastComp, "\\desktop.ini") == 0) {
code = cm_NameI(rootScp, spacep->data,
caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
#endif /* DFS_SUPPORT */
/* now lock the vnode with a callback; returns with newScp locked */
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
smb_SetSMBParm(outp, 8, 0);
smb_SetSMBParm(outp, 9, 0);
smb_SetSMBDataLength(outp, 0);
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return 0;
}
+/* SMB_COM_TREE_DISCONNECT */
long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
smb_tid_t *tidp;
tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
if (tidp) {
lock_ObtainWrite(&smb_rctLock);
- tidp->delete = 1;
+ tidp->deleteOk = 1;
+ smb_ReleaseTID(tidp, TRUE);
lock_ReleaseWrite(&smb_rctLock);
- smb_ReleaseTID(tidp);
}
return 0;
}
+/* SMB_COM_0PEN */
long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
smb_fid_t *fidp;
cm_InitReq(&req);
pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH);
osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
/* save a pointer to the vnode */
fidp->scp = scp;
osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
/* and the user */
cm_HoldUser(userp);
fidp->flags |= (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
smb_SetSMBParm(outp, 0, fidp->fid);
smb_SetSMBParm(outp, 1, smb_Attributes(scp));
smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
/* pass the open mode back; XXXX add access checks */
smb_SetSMBParm(outp, 6, (share & 0xf));
smb_SetSMBDataLength(outp, 0);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
/* notify open */
cm_Open(scp, 0, userp);
smb_unlinkRock_t *rockp;
int caseFold;
int match;
- char shortName[13];
- char *matchName;
+ char matchName[MAX_PATH];
rockp = vrockp;
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- matchName = dep->name;
+ cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
!cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- matchName = shortName;
+ cm_Gen8Dot3Name(dep, matchName, NULL);
/* 8.3 matches are always case insensitive */
match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
}
return code;
}
+/* SMB_COM_DELETE */
long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
int attribute;
attribute = smb_GetSMBParm(inp, 0);
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
osi_Log1(smb_logp, "SMB receive unlink %s",
osi_LogSaveString(smb_logp, pathp));
cm_dirEntryList_t * entry;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+ char normalizedName[MAX_PATH];
+
+ /* Note: entry->name is a non-normalized name */
osi_Log1(smb_logp, "Unlinking %s",
osi_LogSaveString(smb_logp, entry->name));
- code = cm_Unlink(dscp, entry->name, userp, &req);
+
+ cm_NormalizeUtf8String(entry->name, -1, normalizedName,
+ sizeof(normalizedName)/sizeof(char));
+
+ code = cm_Unlink(dscp, entry->name, normalizedName, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
- dscp, entry->name, NULL, TRUE);
+ dscp, normalizedName, NULL, TRUE);
}
}
char *maskp; /* pointer to star pattern of old file name */
int flags; /* tilde, casefold, etc */
char *newNamep; /* ptr to the new file's name */
- char oldName[MAX_PATH];
+ char oldName[MAX_PATH]; /* non-normalized name */
+ char normalizedOldName[MAX_PATH]; /* normalized name */
int any;
} smb_renameRock_t;
smb_renameRock_t *rockp;
int caseFold;
int match;
- char shortName[13]="";
+ char matchName[MAX_PATH];
rockp = (smb_renameRock_t *) vrockp;
+ cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
+ match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
!cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
+ cm_Gen8Dot3Name(dep, matchName, NULL);
+ match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
}
if (match) {
rockp->any = 1;
- strncpy(rockp->oldName, dep->name, sizeof(rockp->oldName)/sizeof(char) - 1);
- rockp->oldName[sizeof(rockp->oldName)/sizeof(char) - 1] = '\0';
+ StringCbCopyA(rockp->oldName, sizeof(rockp->oldName), dep->name);
+ StringCbCopyA(rockp->normalizedOldName, sizeof(rockp->normalizedOldName),
+ matchName);
code = CM_ERROR_STOPNOW;
} else {
code = 0;
rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
rock.newNamep = newLastNamep;
rock.oldName[0] = '\0';
+ rock.normalizedOldName[0] = '\0';
rock.any = 0;
/* Check if the file already exists; if so return error */
/* Check if the old and the new names differ only in case. If so return
* success, else return CM_ERROR_EXISTS
*/
- if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+ if (!code && oldDscp == newDscp && !cm_stricmp_utf8(oldLastNamep, newLastNamep)) {
/* This would be a success only if the old file is *as same as* the new file */
code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
if (code == CM_ERROR_STOPNOW && rock.oldName[0] != '\0') {
- code = cm_Rename(rock.odscp, rock.oldName,
+ code = cm_Rename(rock.odscp, rock.oldName, rock.normalizedOldName,
rock.ndscp, rock.newNamep, rock.userp,
rock.reqp);
/* if the call worked, stop doing the search now, since we
if (oldDscp == newDscp) {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
- filter, oldDscp, oldLastNamep,
+ filter, oldDscp, rock.normalizedOldName,
newLastNamep, TRUE);
} else {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
- filter, oldDscp, oldLastNamep,
+ filter, oldDscp, rock.normalizedOldName,
NULL, TRUE);
if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME,
return code;
}
+/* SMB_COM_RENAME */
long
smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code;
tp = smb_GetSMBData(inp, NULL);
- oldPathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(oldPathp,oldPathp);
- newPathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(newPathp,newPathp);
+ oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
osi_Log2(smb_logp, "smb rename [%s] to [%s]",
osi_LogSaveString(smb_logp, oldPathp),
long code = 0;
smb_rmdirRock_t *rockp;
int match;
- char shortName[13];
- char *matchName;
+ char matchName[MAX_PATH];
rockp = (smb_rmdirRock_t *) vrockp;
- matchName = dep->name;
+ cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
- match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ match = (cm_stricmp_utf8(matchName, rockp->maskp) == 0);
else
match = (strcmp(matchName, rockp->maskp) == 0);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
!cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- matchName = shortName;
- match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ cm_Gen8Dot3Name(dep, matchName, NULL);
+ match = (cm_stricmp_utf8(matchName, rockp->maskp) == 0);
}
if (match) {
return 0;
}
+
long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
cm_InitReq(&req);
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
cm_dirEntryList_t * entry;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+ char normalizedName[MAX_PATH];
+
+ cm_NormalizeUtf8String(entry->name, -1, normalizedName,
+ sizeof(normalizedName)/sizeof(char));
+
osi_Log1(smb_logp, "Removing directory %s",
osi_LogSaveString(smb_logp, entry->name));
- code = cm_RemoveDir(dscp, entry->name, userp, &req);
+ code = cm_RemoveDir(dscp, entry->name, normalizedName, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
- dscp, entry->name, NULL, TRUE);
+ dscp, normalizedName, NULL, TRUE);
}
}
return code;
}
+/* SMB_COM_FLUSH */
long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fid;
userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_OPENWRITE) {
+ if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
cm_scache_t * scp = fidp->scp;
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
char *name;
cm_scache_t *vnode;
char *fullName;
+ char *originalName;
};
int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
osi_hyper_t *offp)
{
- char shortName[13];
+ char matchName[MAX_PATH];
struct smb_FullNameRock *vrockp;
vrockp = (struct smb_FullNameRock *)rockp;
+ cm_NormalizeUtf8String(dep->name, -1, matchName, sizeof(matchName)/sizeof(char));
+
if (!cm_Is8Dot3(dep->name)) {
+ char shortName[13];
+
cm_Gen8Dot3Name(dep, shortName, NULL);
- if (cm_stricmp(shortName, vrockp->name) == 0) {
- vrockp->fullName = strdup(dep->name);
+ if (cm_stricmp_utf8N(shortName, vrockp->name) == 0) {
+ vrockp->fullName = strdup(matchName);
+ vrockp->originalName = strdup(dep->name);
return CM_ERROR_STOPNOW;
}
}
- if (cm_stricmp(dep->name, vrockp->name) == 0 &&
+ if (cm_stricmp_utf8(matchName, vrockp->name) == 0 &&
ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode &&
ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
- vrockp->fullName = strdup(dep->name);
+ vrockp->fullName = strdup(matchName);
+ vrockp->originalName = strdup(dep->name);
return CM_ERROR_STOPNOW;
}
return 0;
}
void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
- char **newPathp, cm_user_t *userp, cm_req_t *reqp)
+ char **newPathp, char ** originalPathp,
+ cm_user_t *userp, cm_req_t *reqp)
{
struct smb_FullNameRock rock;
long code = 0;
+ memset(&rock, 0, sizeof(rock));
rock.name = pathp;
rock.vnode = scp;
code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL);
- if (code == CM_ERROR_STOPNOW)
+ if (code == CM_ERROR_STOPNOW) {
*newPathp = rock.fullName;
- else
+ *originalPathp = rock.originalName;
+ } else {
*newPathp = strdup(pathp);
+ *originalPathp = strdup(pathp);
+ }
}
long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
cm_InitReq(&req);
lock_ObtainWrite(&smb_rctLock);
- if (fidp->delete) {
+ if (fidp->deleteOk) {
osi_Log0(smb_logp, " Fid already closed.");
lock_ReleaseWrite(&smb_rctLock);
return CM_ERROR_BADFD;
}
- fidp->delete = 1;
+ fidp->deleteOk = 1;
lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
}
- lock_ReleaseMutex(&fidp->mx);
- code = cm_FSync(scp, userp, &req);
- lock_ObtainMutex(&fidp->mx);
+ if (smb_AsyncStore != 2) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ lock_ObtainMutex(&fidp->mx);
+ }
}
else
code = 0;
/* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
in zero. */
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
post_syncopdone:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&fidp->mx);
}
if (fidp->flags & SMB_FID_DELONCLOSE) {
- char *fullPathp;
+ char *fullPathp = NULL;
+ char *originalNamep = NULL;
lock_ReleaseMutex(&fidp->mx);
cm_HoldSCache(scp);
delscp = scp;
}
- smb_FullName(dscp, delscp, pathp, &fullPathp, userp, &req);
+ smb_FullName(dscp, delscp, pathp, &fullPathp, &originalNamep, userp, &req);
if (delscp->fileType == CM_SCACHETYPE_DIRECTORY) {
- code = cm_RemoveDir(dscp, fullPathp, userp, &req);
+ code = cm_RemoveDir(dscp, originalNamep, fullPathp, userp, &req);
if (code == 0) {
deleted = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
dscp, fullPathp, NULL, TRUE);
}
} else {
- code = cm_Unlink(dscp, fullPathp, userp, &req);
+ code = cm_Unlink(dscp, originalNamep, fullPathp, userp, &req);
if (code == 0) {
deleted = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
dscp, fullPathp, NULL, TRUE);
}
}
+
+ if (fullPathp)
free(fullPathp);
+ if (originalNamep)
+ free(originalNamep);
+
lock_ObtainMutex(&fidp->mx);
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
if (delscp) {
if (deleted) {
- lock_ObtainMutex(&delscp->mx);
+ lock_ObtainWrite(&delscp->rw);
if (deleted)
delscp->flags |= CM_SCACHEFLAG_DELETED;
- lock_ReleaseMutex(&delscp->mx);
+ lock_ReleaseWrite(&delscp->rw);
}
cm_ReleaseSCache(delscp);
}
if (scp) {
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (nullcreator && scp->creator == userp)
scp->creator = NULL;
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
}
return code;
}
+/* SMB_COM_CLOSE */
long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fid;
/*
* smb_ReadData -- common code for Read, Read And X, and Raw Read
*/
-long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
cm_user_t *userp, long *readp)
{
osi_hyper_t offset;
osi_hyper_t thyper;
osi_hyper_t lastByte;
osi_hyper_t bufferOffset;
- long bufIndex, nbytes;
+ long bufIndex;
+ afs_uint32 nbytes;
int chunk;
int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
cm_req_t req;
+ osi_Log3(smb_logp, "smb_ReadData fid %d, off 0x%x, size 0x%x",
+ fidp->fid, offsetp->LowPart, count);
+
+ *readp = 0;
+
+ lock_ObtainMutex(&fidp->mx);
+ /* make sure we have a readable FD */
+ if (!(fidp->flags & SMB_FID_OPENREAD_LISTDIR)) {
+ osi_Log2(smb_logp, "smb_ReadData fid %d not OPENREAD_LISTDIR flags 0x%x",
+ fidp->fid, fidp->flags);
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFDOP;
+ goto done2;
+ }
+
cm_InitReq(&req);
bufferp = NULL;
offset = *offsetp;
- lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (offset.HighPart == 0) {
chunk = offset.LowPart >> cm_logChunkSize;
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) goto done;
bufferOffset = thyper;
} /* while 1 */
done:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp)
buf_Release(bufferp);
if (code == 0 && sequential)
- cm_ConsiderPrefetch(scp, &lastByte, userp, &req);
+ cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req);
cm_ReleaseSCache(scp);
+ done2:
+ osi_Log3(smb_logp, "smb_ReadData fid %d returns 0x%x read %d bytes",
+ fidp->fid, code, *readp);
return code;
}
/*
* smb_WriteData -- common code for Write and Raw Write
*/
-long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
cm_user_t *userp, long *writtenp)
{
- osi_hyper_t offset;
+ osi_hyper_t offset = *offsetp;
long code = 0;
long written = 0;
- cm_scache_t *scp;
+ cm_scache_t *scp = NULL;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
afs_uint32 nbytes; /* # of bytes to transfer this iteration */
- cm_buf_t *bufferp;
+ cm_buf_t *bufferp = NULL;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
afs_uint32 bufIndex; /* index in buffer where our data is */
- int doWriteBack;
- osi_hyper_t writeBackOffset;/* offset of region to write back when
- * I/O is done */
+ int doWriteBack = 0;
+ osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
DWORD filter = 0;
cm_req_t req;
*writtenp = 0;
- cm_InitReq(&req);
-
- bufferp = NULL;
- doWriteBack = 0;
- offset = *offsetp;
-
lock_ObtainMutex(&fidp->mx);
/* make sure we have a writable FD */
if (!(fidp->flags & SMB_FID_OPENWRITE)) {
fidp->fid, fidp->flags);
lock_ReleaseMutex(&fidp->mx);
code = CM_ERROR_BADFDOP;
- goto done;
+ goto done2;
}
+ cm_InitReq(&req);
+
scp = fidp->scp;
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
/* now, if the new position (thyper) and the old (offset) are in
* different storeback windows, remember to store back the previous
* storeback window when we're done with the write.
+ *
+ * the purpose of this logic is to slow down the CIFS client
+ * in order to avoid the client disconnecting during the CLOSE
+ * operation if there are too many dirty buffers left to write
+ * than can be accomplished during 45 seconds. This used to be
+ * based upon cm_chunkSize but we desire cm_chunkSize to be large
+ * so that we can read larger amounts of data at a time.
*/
- if ((thyper.LowPart & (-cm_chunkSize)) !=
- (offset.LowPart & (-cm_chunkSize))) {
+ if (smb_AsyncStore == 1 &&
+ (thyper.LowPart & ~(smb_AsyncStoreSize-1)) !=
+ (offset.LowPart & ~(smb_AsyncStoreSize-1))) {
/* they're different */
doWriteBack = 1;
writeBackOffset.HighPart = offset.HighPart;
- writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
+ writeBackOffset.LowPart = offset.LowPart & ~(smb_AsyncStoreSize-1);
}
-
+
*writtenp = count;
/* now, copy the data one buffer at a time, until we've filled the
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
lock_ObtainMutex(&bufferp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) goto done;
bufferOffset = thyper;
ConvertLongToLargeInteger(count)),
minLength))) {
if (count < cm_data.buf_blockSize
- && bufferp->dataVersion == -1)
+ && bufferp->dataVersion == CM_BUF_VERSION_BAD)
memset(bufferp->datap, 0,
cm_data.buf_blockSize);
bufferp->dataVersion = scp->dataVersion;
lock_ReleaseMutex(&bufferp->mx);
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&bufferp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) break;
}
if (code) {
} /* while 1 */
done:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp) {
lock_ReleaseMutex(&bufferp->mx);
}
lock_ReleaseMutex(&fidp->mx);
- if (code == 0 && doWriteBack) {
- long code2;
- lock_ObtainMutex(&scp->mx);
- osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
- fidp->fid);
- code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
- osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
- fidp->fid, code2);
- lock_ReleaseMutex(&scp->mx);
- cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
- writeBackOffset.HighPart, cm_chunkSize, 0, userp);
- /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+ if (code == 0) {
+ if (smb_AsyncStore > 0) {
+ if (doWriteBack) {
+ long code2;
+
+ lock_ObtainWrite(&scp->rw);
+ osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
+ fidp->fid);
+ code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
+ osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
+ fidp->fid, code2);
+ lock_ReleaseWrite(&scp->rw);
+ cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
+ writeBackOffset.HighPart,
+ smb_AsyncStoreSize, 0, userp);
+ /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+ }
+ } else {
+ cm_BufWrite(scp, offsetp, *writtenp, 0, userp, &req);
+ }
}
cm_ReleaseSCache(scp);
+ done2:
osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
fidp->fid, code, *writtenp);
return code;
}
+/* SMB_COM_WRITE */
long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fd;
long written = 0, total_written = 0;
unsigned pid;
smb_fid_t *fidp;
+ smb_t* smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
cm_attr_t truncAttr; /* attribute struct used for truncating file */
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = offset.HighPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
if (code) {
osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
return 0;
}
+/* SMB_COM_WRITE_RAW */
long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, raw_write_cont_t *rwcp)
{
osi_hyper_t offset;
long totalCount;
unsigned short fd;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
char *op;
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = offset.HighPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
if (code) {
smb_ReleaseFID(fidp);
return 0;
}
+/* SMB_COM_READ */
long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
osi_hyper_t offset;
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
char *op;
LARGE_INTEGER LOffset, LLength;
cm_key_t key;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = 0;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
if (code) {
smb_ReleaseFID(fidp);
return code;
}
+/* SMB_COM_CREATE_DIRECTORY */
long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp;
initialModeBits = 0777;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
if (strcmp(pathp, "\\") == 0)
return CM_ERROR_EXISTS;
return TRUE;
}
+/* SMB_COM_CREATE and SMB_COM_CREATE_NEW */
long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp;
initialModeBits &= ~0222;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
/* save a pointer to the vnode */
fidp->scp = scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
/* and the user */
fidp->userp = userp;
return 0;
}
+/* SMB_COM_SEEK */
long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
scp = fidp->scp;
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code == 0) {
smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
smb_SetSMBDataLength(outp, 0);
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
smb_ReleaseFID(fidp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (dp->procp) {
/* we have a recognized operation */
+ char * opName = myCrt_Dispatch(inp->inCom);
if (inp->inCom == 0x1d)
/* Raw Write */
code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
else {
- osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",
+ opName,vcp,vcp->lana,vcp->lsn);
code = (*(dp->procp)) (vcp, inp, outp);
- osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d",code,vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d",
+ code,vcp,vcp->lana,vcp->lsn);
#ifdef LOG_PACKET
if ( code == CM_ERROR_BADSMB ||
code == CM_ERROR_BADOP )
- smb_LogPacket(inp);
+ smb_LogPacket(inp);
#endif /* LOG_PACKET */
}
+ newTime = GetTickCount();
+ osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+
if (oldGen != sessionGen) {
- newTime = GetTickCount();
LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION,
newTime - oldTime, ncbp->ncb_length);
- osi_Log2(smb_logp, "Pkt straddled session startup, "
- "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
+ osi_Log3(smb_logp, "Request %s straddled session startup, "
+ "took %d ms, ncb length %d", opName, newTime - oldTime, ncbp->ncb_length);
}
- }
- else {
+
+ FreeSMBStrings(inp);
+ } else {
/* bad opcode, fail the request, after displaying it */
osi_Log1(smb_logp, "Received bad SMB req 0x%X", inp->inCom);
#ifdef LOG_PACKET
smbp = (smb_t *)bufp->data;
outbufp->flags = 0;
+#ifndef NOTRACE
__try
{
+#endif
if (smbp->com == 0x1d) {
/* Special handling for Write Raw */
raw_write_cont_t rwc;
/* TODO: what else needs to be serialized? */
smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
}
+#ifndef NOTRACE
}
__except( smb_ServerExceptionFilter() ) {
}
+#endif
smb_concurrentCalls--;
{
struct smb_packet *bufp;
EVENT_HANDLE retHandle;
- int i;
+ afs_uint32 i;
char eventName[MAX_PATH];
osi_assertx( idx < (sizeof(NCBs) / sizeof(NCBs[0])), "invalid index" );
long code = 0;
long len;
long i;
- int session, thread;
+ afs_uint32 session, thread;
smb_vc_t *vcp = NULL;
int flags = 0;
char rname[NCBNAMSZ+1];
char cname[MAX_COMPUTERNAME_LENGTH+1];
int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
INT_PTR lana = (INT_PTR) parmp;
+ char eventName[MAX_PATH];
+
+ sprintf(eventName,"smb_Listener_lana_%d", (char)lana);
+ ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ thrd_ResetEvent(ListenerShutdown[lana]);
ncbp = GetNCB();
code = Netbios(ncbp);
- if (code == NRC_BRIDGE) {
- int lanaRemaining = 0;
+ if (code == NRC_NAMERR) {
+ /* An smb shutdown or Vista resume must have taken place */
+ osi_Log2(smb_logp,
+ "NCBLISTEN lana=%d failed with NRC_NAMERR.",
+ ncbp->ncb_lana_num, code);
- if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
- ExitThread(1);
+ if (lock_TryMutex(&smb_StartedLock)) {
+ lana_list.lana[i] = LANA_INVALID;
+ lock_ReleaseMutex(&smb_StartedLock);
}
+ break;
+ } else if (code == NRC_BRIDGE || code != 0) {
+ int lanaRemaining = 0;
- osi_Log2(smb_logp,
- "NCBLISTEN lana=%d failed with NRC_BRIDGE. Listener thread exiting.",
- ncbp->ncb_lana_num, code);
+ while (!lock_TryMutex(&smb_StartedLock)) {
+ if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
+ goto exit_thread;
+ Sleep(50);
+ }
+
+ osi_Log2(smb_logp,
+ "NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
+ ncbp->ncb_lana_num, ncb_error_string(code));
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == ncbp->ncb_lana_num) {
- smb_StopListener(ncbp, lana_list.lana[i]);
- lana_list.lana[i] = 255;
+ if (lana_list.lana[i] == lana) {
+ smb_StopListener(ncbp, lana_list.lana[i], FALSE);
+ lana_list.lana[i] = LANA_INVALID;
}
- if (lana_list.lana[i] != 255)
+ if (lana_list.lana[i] != LANA_INVALID)
lanaRemaining++;
}
#endif
);
smb_ListenerState = SMB_LISTENER_STOPPED;
- smb_LANadapter = -1;
+ smb_LANadapter = LANA_INVALID;
lana_list.length = 0;
}
- FreeNCB(ncbp);
- return;
- } else if (code != 0) {
+ lock_ReleaseMutex(&smb_StartedLock);
+ break;
+ }
+#if 0
+ else if (code != 0) {
char tbuffer[AFSPATHMAX];
/* terminate silently if shutdown flag is set */
- if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
- ExitThread(1);
+ while (!lock_TryMutex(&smb_StartedLock)) {
+ if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
+ goto exit_thread;
+ Sleep(50);
}
- osi_Log2(smb_logp,
- "NCBLISTEN lana=%d failed with code %d",
- ncbp->ncb_lana_num, code);
+ osi_Log3(smb_logp,
+ "NCBLISTEN lana=%d failed with code %d [%s]",
+ ncbp->ncb_lana_num, code, ncb_error_string(code));
osi_Log0(smb_logp,
"Client exiting due to network failure. Please restart client.\n");
sprintf(tbuffer,
"Client exiting due to network failure. Please restart client.\n"
- "NCBLISTEN lana=%d failed with code %d",
- ncbp->ncb_lana_num, code);
+ "NCBLISTEN lana=%d failed with code %d [%s]",
+ ncbp->ncb_lana_num, code, ncb_error_string(code));
if (showErrors)
code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
MB_OK|MB_SERVICE_NOTIFICATION);
osi_panic(tbuffer, __FILE__, __LINE__);
+
+ lock_ReleaseMutex(&smb_StartedLock);
+ break;
}
+#endif /* 0 */
/* check for remote conns */
/* first get remote name and insert null terminator */
smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
smbp->rcls = errClass;
}
+
smb_SendPacket(vcp, outp);
smb_FreePacket(outp);
lock_ReleaseMutex(&smb_ListenerLock);
} /* dispatch while loop */
+exit_thread:
FreeNCB(ncbp);
+ thrd_SetEvent(ListenerShutdown[lana]);
+ return;
}
+static void
+smb_LanAdapterChangeThread(void *param)
+{
+ /*
+ * Give the IPAddrDaemon thread a chance
+ * to block before we trigger.
+ */
+ Sleep(30000);
+ smb_LanAdapterChange(0);
+}
+
+void smb_SetLanAdapterChangeDetected(void)
+{
+ int lpid;
+ thread_t phandle;
+
+ lock_ObtainMutex(&smb_StartedLock);
-void smb_LanAdapterChange(void) {
+ if (!powerStateSuspended) {
+ phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_LanAdapterChangeThread,
+ NULL, 0, &lpid, "smb_LanAdapterChange");
+ osi_assertx(phandle != NULL, "smb_LanAdapterChangeThread thread creation failure");
+ thrd_CloseHandle(phandle);
+ }
+
+ smb_LanAdapterChangeDetected = 1;
+ lock_ReleaseMutex(&smb_StartedLock);
+}
+
+void smb_LanAdapterChange(int locked) {
lana_number_t lanaNum;
BOOL bGateway;
char NetbiosName[MAX_NB_NAME_LENGTH] = "";
int change = 0;
+ LANA_ENUM temp_list;
+ long code;
+ int i;
+
+
+ afsi_log("smb_LanAdapterChange");
+
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ smb_LanAdapterChangeDetected = 0;
if (!powerStateSuspended &&
SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway,
- LANA_NETBIOS_NAME_FULL))) {
- if (smb_LANadapter != lanaNum ||
- isGateway != bGateway ||
- strcmp(cm_NetbiosName, NetbiosName))
+ LANA_NETBIOS_NAME_FULL)) &&
+ lanaNum != LANA_INVALID && smb_LANadapter != lanaNum) {
+ if ( isGateway != bGateway ||
+ strcmp(cm_NetbiosName, NetbiosName) ) {
change = 1;
+ } else {
+ NCB *ncbp = GetNCB();
+ ncbp->ncb_command = NCBENUM;
+ ncbp->ncb_buffer = (PUCHAR)&temp_list;
+ ncbp->ncb_length = sizeof(temp_list);
+ code = Netbios(ncbp);
+ if (code == 0) {
+ if (temp_list.length != lana_list.length)
+ change = 1;
+ else {
+ for (i=0; i<lana_list.length; i++) {
+ if ( temp_list.lana[i] != lana_list.lana[i] ) {
+ change = 1;
+ break;
+ }
+ }
+ }
+ }
+ FreeNCB(ncbp);
+ }
}
if (change) {
afsi_log("Lan Adapter Change detected");
- smb_StopListeners();
- smb_RestartListeners();
+ smb_StopListeners(1);
+ smb_RestartListeners(1);
}
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
/* initialize Netbios */
-int smb_NetbiosInit(void)
+int smb_NetbiosInit(int locked)
{
NCB *ncbp;
int i, lana, code, l;
int lana_found = 0;
lana_number_t lanaNum;
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState != SMB_LISTENER_UNINITIALIZED &&
+ smb_ListenerState != SMB_LISTENER_STOPPED) {
+
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
+ return 0;
+ }
/* setup the NCB system */
ncbp = GetNCB();
if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
smb_LANadapter = (lanaNum == LANA_INVALID)? -1: lanaNum;
- if (smb_LANadapter != -1)
+ if (smb_LANadapter != LANA_INVALID)
afsi_log("LAN adapter number %d", smb_LANadapter);
else
afsi_log("LAN adapter number not determined");
afsi_log("smb_localNamep is >%s<", smb_localNamep);
- if (smb_LANadapter == -1) {
+ if (smb_LANadapter == LANA_INVALID) {
ncbp->ncb_command = NCBENUM;
ncbp->ncb_buffer = (PUCHAR)&lana_list;
ncbp->ncb_length = sizeof(lana_list);
code = ncbp->ncb_retcode;
if (code != 0) {
afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
- lana_list.lana[i] = 255; /* invalid lana */
+ lana_list.lana[i] = LANA_INVALID; /* invalid lana */
} else {
afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
}
else {
afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
if (code == NRC_BRIDGE) { /* invalid LANA num */
- lana_list.lana[l] = 255;
+ lana_list.lana[l] = LANA_INVALID;
continue;
}
else if (code == NRC_DUPNAME) {
afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code);
}
if (code != 0 || delname_tried) {
- lana_list.lana[l] = 255;
+ lana_list.lana[l] = LANA_INVALID;
}
else if (code == 0) {
if (!delname_tried) {
}
else {
afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
- lana_list.lana[l] = 255; /* invalid lana */
+ lana_list.lana[l] = LANA_INVALID; /* invalid lana */
}
}
if (code == 0) {
+ smb_LANadapter = lana;
lana_found = 1; /* at least one worked */
}
}
if (!lana_found) {
afsi_log("No valid LANA numbers found!");
lana_list.length = 0;
- smb_LANadapter = -1;
+ smb_LANadapter = LANA_INVALID;
smb_ListenerState = SMB_LISTENER_STOPPED;
cm_VolStatus_Network_Stopped(cm_NetbiosName
#ifdef _WIN64
/* we're done with the NCB now */
FreeNCB(ncbp);
- return ((lana_list.length > 0 && smb_LANadapter != -1) ? 1 : 0);
+ afsi_log("smb_NetbiosInit smb_LANadapter=%d",smb_LANadapter);
+ if (lana_list.length > 0)
+ osi_assert(smb_LANadapter != LANA_INVALID);
+
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
+
+ return (lana_list.length > 0 ? 1 : 0);
}
-void smb_StartListeners()
+void smb_StartListeners(int locked)
{
int i;
int lpid;
thread_t phandle;
- if (smb_ListenerState == SMB_LISTENER_STARTED)
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState == SMB_LISTENER_STARTED) {
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
return;
-
+ }
+
+ afsi_log("smb_StartListeners");
smb_ListenerState = SMB_LISTENER_STARTED;
cm_VolStatus_Network_Started(cm_NetbiosName
#ifdef _WIN64
);
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == 255)
+ if (lana_list.lana[i] == LANA_INVALID)
continue;
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
(void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
osi_assertx(phandle != NULL, "smb_Listener thread creation failure");
thrd_CloseHandle(phandle);
}
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
-void smb_RestartListeners()
+void smb_RestartListeners(int locked)
{
- if (!powerStateSuspended) {
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (powerStateSuspended)
+ afsi_log("smb_RestartListeners called while suspended");
+
+ if (!powerStateSuspended && smb_ListenerState != SMB_LISTENER_UNINITIALIZED) {
if (smb_ListenerState == SMB_LISTENER_STOPPED) {
- if (smb_NetbiosInit())
- smb_StartListeners();
- }
- if (smb_LANadapter == -1)
- smb_LanAdapterChange();
+ if (smb_NetbiosInit(1))
+ smb_StartListeners(1);
+ } else if (smb_LanAdapterChangeDetected) {
+ smb_LanAdapterChange(1);
+ }
}
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
-void smb_StopListener(NCB *ncbp, int lana)
+void smb_StopListener(NCB *ncbp, int lana, int wait)
{
long code;
} else {
afsi_log("Netbios NCBRESET lana %d succeeded", lana);
}
+
+ if (wait)
+ thrd_WaitForSingleObject_Event(ListenerShutdown[lana], INFINITE);
}
-void smb_StopListeners(void)
+void smb_StopListeners(int locked)
{
NCB *ncbp;
int lana, l;
- if (smb_ListenerState == SMB_LISTENER_STOPPED)
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState == SMB_LISTENER_STOPPED) {
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
return;
+ }
+ afsi_log("smb_StopListeners");
smb_ListenerState = SMB_LISTENER_STOPPED;
cm_VolStatus_Network_Stopped(cm_NetbiosName
#ifdef _WIN64
for (l = 0; l < lana_list.length; l++) {
lana = lana_list.lana[l];
- if (lana != 255) {
- smb_StopListener(ncbp, lana);
+ if (lana != LANA_INVALID) {
+ smb_StopListener(ncbp, lana, TRUE);
/* mark the adapter invalid */
- lana_list.lana[l] = 255; /* invalid lana */
+ lana_list.lana[l] = LANA_INVALID; /* invalid lana */
}
}
/* force a re-evaluation of the network adapters */
lana_list.length = 0;
- smb_LANadapter = -1;
+ smb_LANadapter = LANA_INVALID;
FreeNCB(ncbp);
- Sleep(1000); /* give the listener threads a chance to exit */
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
void smb_Init(osi_log_t *logp, int useV3,
struct tm myTime;
EVENT_HANDLE retHandle;
char eventName[MAX_PATH];
+ int startListeners = 0;
smb_TlsRequestSlot = TlsAlloc();
lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
+ lock_InitializeMutex(&smb_StartedLock, "smb started lock");
/* 4 Raw I/O buffers */
smb_RawBufs = calloc(65536,1);
smb_ncbFreeListp = NULL;
smb_packetFreeListp = NULL;
- smb_NetbiosInit();
+ lock_ObtainMutex(&smb_StartedLock);
+ startListeners = smb_NetbiosInit(1);
/* Initialize listener and server structures */
numVCs = 0;
}
/* Start listeners, waiters, servers, and daemons */
-
- smb_StartListeners();
+ if (startListeners)
+ smb_StartListeners(1);
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
NULL, 0, &lpid, "smb_ClientWaiter");
- osi_assertx(phandle != NULL, , "smb_ClientWaiter thread creation failure");
+ osi_assertx(phandle != NULL, "smb_ClientWaiter thread creation failure");
thrd_CloseHandle(phandle);
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
osi_assertx(phandle != NULL, "smb_WaitingLocksDaemon thread creation failure");
thrd_CloseHandle(phandle);
+ lock_ReleaseMutex(&smb_StartedLock);
return;
}
{
NCB *ncbp;
long code = 0;
- int i;
+ afs_uint32 i;
smb_vc_t *vcp;
/*fprintf(stderr, "Entering smb_Shutdown\n");*/
/* Delete Netbios name */
memset((char *)ncbp, 0, sizeof(NCB));
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == 255) continue;
+ if (lana_list.lana[i] == LANA_INVALID) continue;
ncbp->ncb_command = NCBDELNAME;
ncbp->ncb_lana_num = lana_list.lana[i];
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
if (fidp->scp != NULL) {
scp = fidp->scp;
fidp->scp = NULL;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
osi_Log2(smb_logp,"smb_Shutdown fidp 0x%p scp 0x%p", fidp, scp);
cm_ReleaseSCache(scp);
}
if (tidp->userp) {
cm_user_t *userp = tidp->userp;
tidp->userp = NULL;
- lock_ReleaseWrite(&smb_rctLock);
cm_ReleaseUser(userp);
- lock_ObtainWrite(&smb_rctLock);
}
}
}
void smb_LogPacket(smb_packet_t *packet)
{
BYTE *vp, *cp;
+ smb_t * smbp;
unsigned length, paramlen, datalen, i, j;
char buf[81];
char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
osi_Log0(smb_logp, "*** SMB packet dump ***");
+ smbp = (smb_t *) packet->data;
vp = (BYTE *) packet->data;
- datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1)));
- length = paramlen + 2 + datalen;
-
+ paramlen = smbp->wct * 2;
+ datalen = *((WORD *) (smbp->vdata + paramlen));
+ length = sizeof(*smbp) + paramlen + 1 + datalen;
for (i=0;i < length; i+=16)
{
long smb_IsNetworkStarted(void)
{
- return (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0);
+ long rc;
+ lock_ObtainWrite(&smb_globalLock);
+ rc = (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0);
+ lock_ReleaseWrite(&smb_globalLock);
+ return rc;
}