#include <stdio.h>
#include <time.h>
+#include "afsd.h"
#include <osi.h>
#include <rx\rx.h>
#include <rx/rx_prototypes.h>
-
-#include "afsd.h"
#include <WINNT\afsreg.h>
#include "smb.h"
static char *illegalChars = "\\/:*?\"<>|";
BOOL isWindows2000 = FALSE;
-smb_vc_t *active_vcp = NULL;
-
int smbShutdownFlag = 0;
int smb_LogoffTokenTransfer;
smb_waitingLockRequest_t *smb_allWaitingLocks;
+DWORD smb_TlsRequestSlot = -1;
+
/* forward decl */
void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
NCB *ncbp, raw_write_cont_t *rwcp);
/* Faux server GUID. This is never checked. */
GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+void smb_ResetServerPriority()
+{
+ void * p = TlsGetValue(smb_TlsRequestSlot);
+ if (p) {
+ free(p);
+ TlsSetValue(smb_TlsRequestSlot, NULL);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ }
+}
+
+void smb_SetRequestStartTime()
+{
+ time_t * tp = malloc(sizeof(time_t));
+ if (tp) {
+ *tp = osi_Time();
+
+ if (!TlsSetValue(smb_TlsRequestSlot, tp))
+ free(tp);
+ }
+}
+
+void smb_UpdateServerPriority()
+{
+ time_t *tp = TlsGetValue(smb_TlsRequestSlot);
+
+ if (tp) {
+ time_t now = osi_Time();
+
+ /* Give one priority boost for each 15 seconds */
+ SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
+ }
+}
+
+
const char * ncb_error_string(int code)
{
const char * s;
return "(2d)ReceiveV3OpenX";
case 0x2e:
return "(2e)ReceiveV3ReadX";
+ case 0x2f:
+ return "(2f)ReceiveV3WriteX";
case 0x32:
return "(32)ReceiveV3Tran2A";
case 0x33:
struct tm localJunk;
time_t t = unixTime;
- ltp = localtime((time_t*) &t);
+ ltp = localtime(&t);
/* if we fail, make up something */
if (!ltp) {
lock_ObtainWrite(&smb_rctLock);
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
- if (lsn == vcp->lsn && lana == vcp->lana) {
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+
+ if (lsn == vcp->lsn && lana == vcp->lana &&
+ !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
smb_HoldVCNoLock(vcp);
break;
}
lock_ObtainWrite(&smb_globalLock);
vcp->vcID = ++numVCs;
lock_ReleaseWrite(&smb_globalLock);
+ vcp->magic = SMB_VC_MAGIC;
vcp->refCount = 2; /* smb_allVCsp and caller */
vcp->tidCounter = 1;
vcp->fidCounter = 1;
void smb_ReleaseVCInternal(smb_vc_t *vcp)
{
smb_vc_t **vcpp;
+ smb_vc_t * avcp;
-#ifdef DEBUG
- osi_assert(vcp->refCount-- != 0);
-#else
vcp->refCount--;
-#endif
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;
- }
+ 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);
+#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++;
+ }
}
}
smb_user_t *uidpNext;
smb_vc_t **vcpp;
+
+ lock_ObtainMutex(&vcp->mx);
+ if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
+ lock_ReleaseMutex(&vcp->mx);
+ osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
+ return;
+ }
+ vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
+ lock_ReleaseMutex(&vcp->mx);
osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
lock_ObtainWrite(&smb_rctLock);
+ /* remove VCP from smb_allVCsp */
+ for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+ if ((*vcpp)->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+ if (*vcpp == vcp) {
+ *vcpp = vcp->nextp;
+ vcp->nextp = smb_deadVCsp;
+ smb_deadVCsp = vcp;
+ /* Hold onto the reference until we are done with this function */
+ break;
+ }
+ }
+
for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
- if (fidpIter->flags & SMB_FID_DELETE)
+ if (fidpIter->delete)
continue;
fid = fidpIter->fid;
smb_HoldFIDNoLock(fidpIter);
lock_ReleaseWrite(&smb_rctLock);
- /* smb_CloseFID sets SMB_FID_DELETE on Success */
smb_CloseFID(vcp, fidpIter, NULL, 0);
smb_ReleaseFID(fidpIter);
for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
tidpNext = tidpIter->nextp;
-
- if (tidpIter->flags & SMB_TIDFLAG_DELETE)
+ if (tidpIter->delete)
continue;
+ tidpIter->delete = 1;
tid = tidpIter->tid;
osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
smb_HoldTIDNoLock(tidpIter);
lock_ReleaseWrite(&smb_rctLock);
- lock_ObtainMutex(&tidpIter->mx);
- tidpIter->flags |= SMB_TIDFLAG_DELETE;
- lock_ReleaseMutex(&tidpIter->mx);
-
smb_ReleaseTID(tidpIter);
lock_ObtainWrite(&smb_rctLock);
for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
uidpNext = uidpIter->nextp;
-
- if (uidpIter->flags & SMB_USERFLAG_DELETE)
+ if (uidpIter->delete)
continue;
+ uidpIter->delete = 1;
/* do not add an additional reference count for the smb_user_t
* as the smb_vc_t already is holding a reference */
lock_ReleaseWrite(&smb_rctLock);
- lock_ObtainMutex(&uidpIter->mx);
- uidpIter->flags |= SMB_USERFLAG_DELETE;
- lock_ReleaseMutex(&uidpIter->mx);
-
smb_ReleaseUID(uidpIter);
lock_ObtainWrite(&smb_rctLock);
uidpNext = vcp->usersp;
}
- /* remove VCP from smb_allVCsp */
- for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
- if (*vcpp == vcp) {
- *vcpp = vcp->nextp;
- vcp->nextp = smb_deadVCsp;
- smb_deadVCsp = vcp;
- /* We intentionally do not keep a reference to the
- * vcp once it is placed on the deadVCsp list. This
- * allows the refcount to reach 0 so we can delete
- * it. */
- smb_ReleaseVCNoLock(vcp);
- break;
- }
- }
+ /* The vcp is now on the deadVCsp list. We intentionally drop the
+ * reference so that the refcount can reach 0 and we can delete it */
+ smb_ReleaseVCNoLock(vcp);
+
lock_ReleaseWrite(&smb_rctLock);
osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
}
userp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(tidp->refCount-- > 0);
- if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
+ if (tidp->refCount == 0 && (tidp->delete)) {
ltpp = &tidp->vcp->tidsp;
for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
if (tp == tidp)
}
}
+cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
+{
+ cm_user_t *up = NULL;
+
+ if (!uidp)
+ return NULL;
+
+ lock_ObtainMutex(&uidp->mx);
+ if (uidp->unp) {
+ up = uidp->unp->userp;
+ cm_HoldUser(up);
+ }
+ lock_ReleaseMutex(&uidp->mx);
+
+ return up;
+}
+
+
/* retrieve a held reference to a user structure corresponding to an incoming
* request.
* corresponding release function is cm_ReleaseUser.
*/
-cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
+cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
{
smb_user_t *uidp;
cm_user_t *up = NULL;
if (!uidp)
return NULL;
- lock_ObtainMutex(&uidp->mx);
- if (uidp->unp) {
- up = uidp->unp->userp;
- cm_HoldUser(up);
- }
- lock_ReleaseMutex(&uidp->mx);
+ up = smb_GetUserFromUID(uidp);
smb_ReleaseUID(uidp);
return up;
smb_vc_t *vcp = NULL;
smb_ioctl_t *ioctlp;
+ lock_ObtainMutex(&fidp->mx);
lock_ObtainWrite(&smb_rctLock);
osi_assert(fidp->refCount-- > 0);
- lock_ObtainMutex(&fidp->mx);
- if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
+ if (fidp->refCount == 0 && (fidp->delete)) {
vcp = fidp->vcp;
fidp->vcp = NULL;
scp = fidp->scp; /* release after lock is released */
userp = fidp->userp;
fidp->userp = NULL;
- osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
+ if (vcp->fidsp)
+ osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
thrd_CloseHandle(fidp->raw_write_event);
/* and see if there is ioctl stuff to free */
free(ioctlp->outAllocp);
free(ioctlp);
}
-
lock_ReleaseMutex(&fidp->mx);
lock_FinalizeMutex(&fidp->mx);
free(fidp);
LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
#endif /* !DJGPP */
- osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
- vcp, vcp->usersp);
-
- lock_ObtainWrite(&smb_globalLock);
- lock_ObtainMutex(&vcp->mx);
- vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- dead_sessions[vcp->session] = TRUE;
- lock_ReleaseMutex(&vcp->mx);
- lock_ReleaseWrite(&smb_globalLock);
- smb_CleanupDeadVC(vcp);
+ lock_ObtainMutex(&vcp->mx);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
}
if (localNCB)
fd = smb_GetSMBParm(inp, 0);
count = smb_GetSMBParm(inp, 3);
minCount = smb_GetSMBParm(inp, 4);
- offset.HighPart = 0; /* too bad */
offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
- osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
- fd, offset.LowPart, count);
+ if (*inp->wctp == 10) {
+ /* we were sent a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+ offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
+
+ if (LargeIntegerLessThanZero(offset)) {
+ osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
+ goto send1;
+ }
+#else
+ if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
+ osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset. Dropping request.");
+ goto send1;
+ } else {
+ offset.HighPart = 0;
+ }
+#endif
+ } else {
+ /* we were sent a request with 32-bit file offsets */
+ offset.HighPart = 0;
+ }
+
+ osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
+ fd, offset.HighPart, offset.LowPart, count);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp)
key = cm_GenerateKey(vcp->vcID, pid, fd);
- LOffset.HighPart = 0;
+ LOffset.HighPart = offset.HighPart;
LOffset.LowPart = offset.LowPart;
LLength.HighPart = 0;
LLength.LowPart = count;
}
lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
#ifndef DJGPP
code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
#endif
+#ifdef AFS_LARGEFILES
+ NTNEGOTIATE_CAPABILITY_LARGEFILES |
+#endif
NTNEGOTIATE_CAPABILITY_NTFIND |
NTNEGOTIATE_CAPABILITY_RAWMODE |
NTNEGOTIATE_CAPABILITY_NTSMB;
void smb_CheckVCs(void)
{
- smb_vc_t * vcp;
+ smb_vc_t * vcp, *nextp;
smb_packet_t * outp = GetPacket();
smb_t *smbp;
- for ( vcp=smb_allVCsp; vcp; vcp = vcp->nextp )
+ lock_ObtainWrite(&smb_rctLock);
+ for ( vcp=smb_allVCsp, nextp=NULL; vcp; vcp = nextp )
{
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+
+ nextp = vcp->nextp;
+
if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
continue;
+ smb_HoldVCNoLock(vcp);
+ if (nextp)
+ smb_HoldVCNoLock(nextp);
smb_FormatResponsePacket(vcp, NULL, outp);
smbp = (smb_t *)outp;
outp->inCom = smbp->com = 0x2b /* Echo */;
smb_SetSMBParm(outp, 0, 0);
smb_SetSMBDataLength(outp, 0);
+ lock_ReleaseWrite(&smb_rctLock);
smb_SendPacket(vcp, outp);
- }
+ lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseVCNoLock(vcp);
+ if (nextp)
+ smb_ReleaseVCNoLock(nextp);
+ }
+ lock_ReleaseWrite(&smb_rctLock);
smb_FreePacket(outp);
}
return CM_ERROR_BADSMB;
strcpy(shareName, tp+1);
- userp = smb_GetUser(vcp, inp);
-
lock_ObtainMutex(&vcp->mx);
newTid = vcp->tidCounter++;
lock_ReleaseMutex(&vcp->mx);
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ userp = smb_GetUserFromUID(uidp);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
if (uidp)
smb_ReleaseUID(uidp);
osi_Log3(smb_logp, "SMB search dir cookie 0x%x, connection %d, attr 0x%x",
nextCookie, dsp->cookie, attribute);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* try to get the vnode for the path name next */
lock_ObtainMutex(&dsp->mx);
rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return code;
}
-
+
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
cm_ReleaseSCache(newScp);
rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* we shouldn't need this for V3 requests, but we seem to */
caseFold = CM_FLAG_CASEFOLD;
* in a readonly volume doesn't mean it shojuld be marked as RO
*/
if (newScp->fileType == CM_SCACHETYPE_DIRECTORY ||
- newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ newScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ newScp->fileType == CM_SCACHETYPE_INVALID)
attrs = SMB_ATTR_DIRECTORY;
else
attrs = 0;
/* find the tree and free it */
tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
if (tidp) {
- lock_ObtainMutex(&tidp->mx);
- tidp->flags |= SMB_TIDFLAG_DELETE;
- lock_ReleaseMutex(&tidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
+ tidp->delete = 1;
+ lock_ReleaseWrite(&smb_rctLock);
smb_ReleaseTID(tidp);
}
return 0;
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
DWORD filter;
cm_req_t req;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
cm_ReleaseUser(userp);
DWORD filter;
cm_req_t req;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
/* now create the hardlink */
osi_Log1(smb_logp," Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep));
code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req);
- osi_Log1(smb_logp," Link returns %d", code);
+ osi_Log1(smb_logp," Link returns 0x%x", code);
/* Handle Change Notification */
if (code == 0) {
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
}
lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_OPENWRITE)
- code = cm_FSync(fidp->scp, userp, &req);
- else
+ if (fidp->flags & SMB_FID_OPENWRITE) {
+ cm_scache_t * scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ cm_ReleaseSCache(scp);
+ } else {
code = 0;
- lock_ReleaseMutex(&fidp->mx);
+ lock_ReleaseMutex(&fidp->mx);
+ }
smb_ReleaseFID(fidp);
cm_req_t req;
cm_scache_t *dscp = fidp->NTopen_dscp;
char *pathp = fidp->NTopen_pathp;
+ cm_scache_t * scp;
osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
fidp, fidp->fid, vcp);
cm_InitReq(&req);
- lock_ObtainMutex(&fidp->mx);
-
- if (fidp->flags & SMB_FID_DELETE) {
+ lock_ObtainWrite(&smb_rctLock);
+ if (fidp->delete) {
osi_Log0(smb_logp, " Fid already closed.");
- lock_ReleaseMutex(&fidp->mx);
+ lock_ReleaseWrite(&smb_rctLock);
return CM_ERROR_BADFD;
}
+ fidp->delete = 1;
+ lock_ReleaseWrite(&smb_rctLock);
- fidp->flags |= SMB_FID_DELETE;
-
+ lock_ObtainMutex(&fidp->mx);
/* Don't jump the gun on an async raw write */
while (fidp->raw_writers) {
lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&fidp->mx);
}
+ scp = fidp->scp;
+ if (scp)
+ cm_HoldSCache(scp);
+
/* watch for ioctl closes, and read-only opens */
- if (fidp->scp != NULL &&
+ if (scp != NULL &&
(fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
== SMB_FID_OPENWRITE) {
if (dosTime != 0 && dosTime != -1) {
- fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+ scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
/* This fixes defect 10958 */
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
}
- code = cm_FSync(fidp->scp, userp, &req);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ lock_ObtainMutex(&fidp->mx);
}
else
code = 0;
/* unlock any pending locks */
- if (!(fidp->flags & SMB_FID_IOCTL) && fidp->scp &&
- fidp->scp->fileType == CM_SCACHETYPE_FILE) {
+ if (!(fidp->flags & SMB_FID_IOCTL) && scp &&
+ scp->fileType == CM_SCACHETYPE_FILE) {
cm_key_t key;
- cm_scache_t * scp;
long tcode;
- /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
+ lock_ReleaseMutex(&fidp->mx);
+
+ /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
in zero. */
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
- scp = fidp->scp;
- cm_HoldSCache(scp);
lock_ObtainMutex(&scp->mx);
tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
post_syncopdone:
lock_ReleaseMutex(&scp->mx);
- cm_ReleaseSCache(scp);
+ lock_ObtainMutex(&fidp->mx);
}
if (fidp->flags & SMB_FID_DELONCLOSE) {
char *fullPathp;
- smb_FullName(dscp, fidp->scp, pathp, &fullPathp, userp, &req);
- if (fidp->scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_FullName(dscp, scp, pathp, &fullPathp, userp, &req);
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
code = cm_RemoveDir(dscp, fullPathp, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
dscp, fullPathp, NULL, TRUE);
}
free(fullPathp);
+ lock_ObtainMutex(&fidp->mx);
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
+ /* if this was a newly created file, then clear the creator
+ * in the stat cache entry. */
+ if (fidp->flags & SMB_FID_CREATED) {
+ lock_ObtainMutex(&scp->mx);
+ if (scp->creator == userp)
+ scp->creator = NULL;
+ lock_ReleaseMutex(&scp->mx);
+ fidp->flags &= ~SMB_FID_CREATED;
+ }
+
if (fidp->flags & SMB_FID_NTOPEN) {
fidp->NTopen_dscp = NULL;
fidp->NTopen_pathp = NULL;
if (dscp)
cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
+
if (pathp)
free(pathp);
return CM_ERROR_BADFD;
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
code = smb_CloseFID(vcp, fidp, userp, dosTime);
if (fidp->curr_chunk == fidp->prev_chunk + 1)
sequential = 1;
}
+ lock_ReleaseMutex(&fidp->mx);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
done:
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
if (bufferp)
buf_Release(bufferp);
offset = *offsetp;
lock_ObtainMutex(&fidp->mx);
+ /* make sure we have a writable FD */
+ if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+ osi_Log2(smb_logp, "smb_WriteData fid %d not OPENWRITE flags 0x%x",
+ fidp->fid, fidp->flags);
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFDOP;
+ goto done;
+ }
+
scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainMutex(&scp->mx);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
if (code)
goto done;
- /* make sure we have a writable FD */
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- lock_ReleaseMutex(&fidp->mx);
- code = CM_ERROR_BADFDOP;
- goto done;
- }
-
/* now we have the entry locked, look up the length */
fileLength = scp->length;
minLength = fileLength;
buf_Release(bufferp);
}
+ lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
&& (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
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 %d",
- fidp->fid,code2);
+ 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);
}
- osi_Log3(smb_logp, "smb_WriteData fid %d returns %d written %d",
+ cm_ReleaseSCache(scp);
+
+ osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
fidp->fid, code, *writtenp);
return code;
}
return code;
}
lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* special case: 0 bytes transferred means truncate to this position */
if (count == 0) {
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
count -= written;
total_written += written;
written = 0;
fd = smb_GetSMBParm(inp, 0);
fidp = smb_FindFID(vcp, fd, 0);
- osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
- rwcp->offset.LowPart, rwcp->count);
+ osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
+ rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
#ifndef DJGPP
rawBuf = rwcp->buf;
fd = smb_GetSMBParm(inp, 0);
totalCount = smb_GetSMBParm(inp, 1);
count = smb_GetSMBParm(inp, 10);
- offset.HighPart = 0; /* too bad */
- offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
writeMode = smb_GetSMBParm(inp, 7);
op = (char *) inp->data;
op += smb_GetSMBParm(inp, 11);
+ offset.HighPart = 0;
+ offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+ if (*inp->wctp == 14) {
+ /* we received a 64-bit file offset */
+#ifdef AFS_LARGEFILES
+ offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+
+ if (LargeIntegerLessThanZero(offset)) {
+ osi_Log2(smb_logp,
+ "smb_ReceiveCoreWriteRaw received negative file offset 0x%x:%08x",
+ offset.HighPart, offset.LowPart);
+ return CM_ERROR_BADSMB;
+ }
+#else
+ if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+ osi_Log0(smb_logp,
+ "smb_ReceiveCoreWriteRaw received 64-bit file offset, but we don't support large files");
+ return CM_ERROR_BADSMB;
+ }
+
+ offset.HighPart = 0;
+#endif
+ } else {
+ offset.HighPart = 0; /* 32-bit file offset */
+ }
+
osi_Log4(smb_logp,
- "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
- fd, offset.LowPart, count, writeMode);
+ "smb_ReceiveCoreWriteRaw fd %d, off 0x%x:%08x, size 0x%x",
+ fd, offset.HighPart, offset.LowPart, count);
+ osi_Log1(smb_logp,
+ " WriteRaw WriteMode 0x%x",
+ writeMode);
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
}
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/*
* Work around bug in NT client
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
+
count -= written;
total_written += written;
written = 0;
return code;
}
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(count));
+
rwcp->code = 0;
rwcp->buf = rawBuf;
- rwcp->offset.HighPart = 0;
- rwcp->offset.LowPart = offset.LowPart + count;
+ rwcp->offset.HighPart = offset.HighPart;
+ rwcp->offset.LowPart = offset.LowPart;
rwcp->count = totalCount - count;
rwcp->writeMode = writeMode;
rwcp->alreadyWritten = total_written;
return code;
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* remember this for final results */
smb_SetSMBParm(outp, 0, count);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
afs_uint32 dosTime;
char *tidPathp;
cm_req_t req;
+ int created = 0; /* the file was new */
cm_InitReq(&req);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (!excl && code == CM_ERROR_EXISTS) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
/* always create it open for read/write */
fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
+ /* remember that the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
/* save a pointer to the vnode */
fidp->scp = scp;
/* and the user */
long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
+ osi_hyper_t new_offset;
long offset;
int whence;
unsigned short fd;
}
lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code == 0) {
if (whence == 1) {
/* offset from current offset */
- offset += fidp->offset;
+ new_offset = LargeIntegerAdd(fidp->offset,
+ ConvertLongToLargeInteger(offset));
}
else if (whence == 2) {
/* offset from current EOF */
- offset += scp->length.LowPart;
+ new_offset = LargeIntegerAdd(scp->length,
+ ConvertLongToLargeInteger(offset));
+ } else {
+ new_offset = ConvertLongToLargeInteger(offset);
}
- fidp->offset = offset;
- smb_SetSMBParm(outp, 0, offset & 0xffff);
- smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
+
+ fidp->offset = new_offset;
+ smb_SetSMBParm(outp, 0, new_offset.LowPart & 0xffff);
+ smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
smb_SetSMBDataLength(outp, 0);
}
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
smb_SendPacket(vcp, outp);
thrd_Decrement(&ongoingOps);
- if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
- if (active_vcp != vcp) {
- if (active_vcp) {
- osi_Log2(smb_logp,
- "Replacing active_vcp %x with %x", active_vcp, vcp);
- smb_ReleaseVC(active_vcp);
- }
- smb_HoldVC(vcp);
- lock_ObtainWrite(&smb_globalLock);
- active_vcp = vcp;
- lock_ReleaseWrite(&smb_globalLock);
- }
- last_msg_time = GetTickCount();
- } else if (active_vcp == vcp) { /* the vcp is dead */
- smb_ReleaseVC(active_vcp);
- lock_ObtainWrite(&smb_globalLock);
- active_vcp = NULL;
- lock_ReleaseWrite(&smb_globalLock);
- }
return;
}
smb_ReleaseVC(vcp);
vcp = NULL;
}
+
+ smb_ResetServerPriority();
+
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
FALSE, INFINITE);
/* Client closed session */
vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
if (vcp) {
- lock_ObtainWrite(&smb_globalLock);
+ lock_ObtainMutex(&vcp->mx);
if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
vcp, vcp->usersp);
- lock_ObtainMutex(&vcp->mx);
vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- dead_sessions[vcp->session] = TRUE;
lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
lock_ReleaseWrite(&smb_globalLock);
smb_CleanupDeadVC(vcp);
smb_ReleaseVC(vcp);
vcp = NULL;
- }
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
}
goto doneWithNCB;
default:
/* A weird error code. Log it, sleep, and continue. */
vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+ if (vcp)
+ lock_ObtainMutex(&vcp->mx);
if (vcp && vcp->errorCount++ > 3) {
osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
- lock_ObtainWrite(&smb_globalLock);
if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
vcp, vcp->usersp);
- lock_ObtainMutex(&vcp->mx);
vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- dead_sessions[vcp->session] = TRUE;
lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
lock_ReleaseWrite(&smb_globalLock);
smb_CleanupDeadVC(vcp);
smb_ReleaseVC(vcp);
vcp = NULL;
- }
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
goto doneWithNCB;
}
else {
+ if (vcp)
+ lock_ReleaseMutex(&vcp->mx);
thrd_Sleep(1000);
- thrd_SetEvent(SessionEvents[idx_session]);
+ thrd_SetEvent(SessionEvents[idx_session]);
}
- continue;
+ continue;
}
/* Success, so now dispatch on all the data in the packet */
* then we are in big trouble. This means either :
* a) we have the wrong NCB.
* b) Netbios screwed up the call.
+ * c) The VC was already marked dead before we were able to
+ * process the call
* Obviously this implies that
* ( LSNs[idx_session] != ncbp->ncb_lsn ||
* lanas[idx_session] != ncbp->ncb_lana_num )
ncbp->ncb_lana_num);
/* Also log in the trace log. */
- osi_Log4(smb_logp, "Server: BAD VCP!"
+ osi_Log4(smb_logp, "Server: VCP does not exist!"
"LSNs[idx_session]=[%d],"
"lanas[idx_session]=[%d],"
"ncbp->ncb_lsn=[%d],"
continue;
}
+ smb_SetRequestStartTime();
+
vcp->errorCount = 0;
bufp = (struct smb_packet *) ncbp->ncb_buffer;
#ifdef DJGPP
smb_FreePacket(outp);
lock_ObtainMutex(&vcp->mx);
- vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- lock_ReleaseMutex(&vcp->mx);
- smb_CleanupDeadVC(vcp);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
} else {
/* assert that we do not exceed the maximum number of sessions or NCBs.
* we should probably want to wait for a session to be freed in case
EVENT_HANDLE retHandle;
char eventName[MAX_PATH];
+ smb_TlsRequestSlot = TlsAlloc();
+
#ifndef DJGPP
smb_MBfunc = aMBfunc;
#endif /* DJGPP */
smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
+ smb_dispatchTable[0x2f].procp = smb_ReceiveV3WriteX;
+ smb_dispatchTable[0x2f].flags |= SMB_DISPATCHFLAG_CHAINED;
smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A; /* both are same */
smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
smb_fid_t *fidp;
smb_tid_t *tidp;
- for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+
+ for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
{
if (fidp->scp != NULL) {
cm_scache_t * scp;
}
}
lock_ReleaseWrite(&smb_rctLock);
+
+ TlsFree(smb_TlsRequestSlot);
}
/* Get the UNC \\<servername>\<sharename> prefix. */
*cp = 0;
- osi_Log0( smb_logp, osi_LogSaveString(smb_logp, buf));
+ osi_Log1( smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
}
osi_Log0(smb_logp, "*** End SMB packet dump ***");