From 0eeab1d6757126f25f5e11cbe44e76323bd2d8c4 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 16 Jan 2006 02:06:58 +0000 Subject: [PATCH] STABLE14-windows-vc-locks-and-more-20060115 This patch fixes several issues: * the smb virtual circuits can be active and/or dead. this patch improves the handling of vc's making the transition from active to dead * correct the refcounts on the smb_user_t and smb_vc_t objects * replace the deprecated GetCurrentTime() with GetTickCounts() which is the new name. This function needs to be replaced with something else because its return value wraps after 49.7 days * hold the correct locks when adjusting the scp->fileLocksH queue (cherry picked from commit 880a6b66a5477e092d5bb74febbf24639d786c64) --- src/WINNT/afsd/afsd_eventmessages.mc | 18 + src/WINNT/afsd/cm_callback.c | 14 +- src/WINNT/afsd/cm_conn.c | 6 +- src/WINNT/afsd/cm_server.h | 2 +- src/WINNT/afsd/cm_vnodeops.c | 12 +- src/WINNT/afsd/smb.c | 118 ++++--- src/WINNT/afsd/smb.h | 2 + src/WINNT/afsd/smb3.c | 18 +- src/WINNT/afsd/smb_ioctl.c | 506 ++++++++++++++------------- 9 files changed, 369 insertions(+), 327 deletions(-) diff --git a/src/WINNT/afsd/afsd_eventmessages.mc b/src/WINNT/afsd/afsd_eventmessages.mc index 37f86ac9b..89adeccb8 100644 --- a/src/WINNT/afsd/afsd_eventmessages.mc +++ b/src/WINNT/afsd/afsd_eventmessages.mc @@ -106,4 +106,22 @@ Flush volumes thread received unrecognized event. . +MessageId= +Severity=Warning +Facility=System +SymbolicName=MSG_SMB_SEND_PACKET_FAILURE +Language=English +Unable to Send SMB Packet: %1. +. + + +MessageId= +Severity=Warning +Facility=System +SymbolicName=MSG_UNEXPECTED_SMB_SESSION_CLOSE +Language=English +Unexpected SMB Session Close: %1. +. + + ;#endif /* __AFSD_EVENTMESSAGES_H_ 1 */ diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index 4fa09dc69..d1617de9f 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -1668,8 +1668,8 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp, lock_ReleaseMutex(&scp->mx); /* now make the RPC */ - osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%x cell %d vol %d uniq %d", - (long) scp, scp->fid.cell, scp->fid.volume, scp->fid.unique); + osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%x vol %u vn %u uniq %u", + (long) scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique); do { code = cm_Conn(&sfid, userp, reqp, &connp); if (code) @@ -1684,11 +1684,11 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp, &cbr, code)); code = cm_MapRPCError(code, reqp); if (code) - osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%x cell %d vol %d", - code, (long) scp, scp->fid.cell, scp->fid.volume); + osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%x vol %u vn %u", + code, (long) scp, scp->fid.volume, scp->fid.vnode); else - osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%x cell %d vol %d uniq %d", - (long) scp, scp->fid.cell, scp->fid.volume, scp->fid.unique); + osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%x vol %u vn %u uniq %u", + (long) scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique); lock_ObtainMutex(&scp->mx); if (code == 0) { @@ -1702,7 +1702,7 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp, /* now check to see if we got an error */ if (code) { osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%x -->",code, scp); - osi_Log4(afsd_logp, " cell %d vol %d vn %d uniq %d", + osi_Log4(afsd_logp, " cell %u vol %u vn %u uniq %u", scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique); return code; } diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 1478d05a2..4bb8247f1 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -90,7 +90,7 @@ void cm_InitReq(cm_req_t *reqp) { memset((char *)reqp, 0, sizeof(cm_req_t)); #ifndef DJGPP - reqp->startTime = GetCurrentTime(); + reqp->startTime = GetTickCount(); #else gettimeofday(&reqp->startTime, NULL); #endif @@ -189,7 +189,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, /* timeleft - get if from reqp the same way as cmXonnByMServers does */ #ifndef DJGPP - timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; + timeUsed = (GetTickCount() - reqp->startTime) / 1000; #else gettimeofday(&now, NULL); timeUsed = sub_time(now, reqp->startTime) / 1000; @@ -536,7 +536,7 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, *connpp = NULL; #ifndef DJGPP - timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; + timeUsed = (GetTickCount() - reqp->startTime) / 1000; #else gettimeofday(&now, NULL); timeUsed = sub_time(now, reqp->startTime) / 1000; diff --git a/src/WINNT/afsd/cm_server.h b/src/WINNT/afsd/cm_server.h index 265eb1a1a..901fe5ddf 100644 --- a/src/WINNT/afsd/cm_server.h +++ b/src/WINNT/afsd/cm_server.h @@ -25,7 +25,7 @@ typedef struct cm_server { struct sockaddr_in addr; /* by mx */ int type; /* by mx */ struct cm_conn *connsp; /* locked by cm_connLock */ - long flags; /* by mx */ + long flags; /* by mx */ struct cm_cell *cellp; /* cell containing this server */ unsigned long refCount; /* locked by cm_serverLock */ osi_mutex_t mx; diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index add22462e..0be176fb6 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -3558,9 +3558,8 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType, fileLock->lastUpdate = (code == 0) ? time(NULL) : 0; - osi_QAddT(&scp->fileLocksH, &scp->fileLocksT, &fileLock->fileq); - lock_ObtainWrite(&cm_scacheLock); + osi_QAddT(&scp->fileLocksH, &scp->fileLocksT, &fileLock->fileq); cm_HoldSCacheNoLock(scp); fileLock->scp = scp; osi_QAdd(&cm_allFileLocks, &fileLock->q); @@ -3899,20 +3898,19 @@ long cm_Unlock(cm_scache_t *scp, return 0; } + lock_ReleaseRead(&cm_scacheLock); + /* discard lock record */ + lock_ObtainWrite(&cm_scacheLock); if (scp->fileLocksT == q) scp->fileLocksT = osi_QPrev(q); osi_QRemove(&scp->fileLocksH, q); - lock_ReleaseRead(&cm_scacheLock); - /* * Don't delete it here; let the daemon delete it, to simplify * the daemon's traversal of the list. */ - lock_ObtainWrite(&cm_scacheLock); - if(IS_LOCK_ACCEPTED(fileLock)) { if(fileLock->lockType == LockRead) scp->sharedLocks--; @@ -4511,9 +4509,11 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead) handleCode: if (code != 0 && code != CM_ERROR_WOULDBLOCK) { + lock_ObtainWrite(&cm_scacheLock); if (scp->fileLocksT == &oldFileLock->fileq) scp->fileLocksT = osi_QPrev(&oldFileLock->fileq); osi_QRemove(&scp->fileLocksH, &oldFileLock->fileq); + lock_ReleaseWrite(&cm_scacheLock); } else if (code == 0 && IS_LOCK_WAITLOCK(oldFileLock)) { scp->serverLock = newLock; } diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 1c326bbfe..726c18a05 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -821,10 +821,10 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana) vcp = malloc(sizeof(*vcp)); memset(vcp, 0, sizeof(*vcp)); vcp->vcID = numVCs++; - vcp->refCount = 1; + vcp->refCount = 2; /* smb_allVCsp and caller */ vcp->tidCounter = 1; vcp->fidCounter = 1; - vcp->uidCounter = 1; /* UID 0 is reserved for blank user */ + vcp->uidCounter = 1; /* UID 0 is reserved for blank user */ vcp->nextp = smb_allVCsp; smb_allVCsp = vcp; lock_InitializeMutex(&vcp->mx, "vc_t mutex"); @@ -882,25 +882,31 @@ int smb_IsStarMask(char *maskp) return 0; } -void smb_ReleaseVCNoLock(smb_vc_t *vcp) +void smb_ReleaseVCInternal(smb_vc_t *vcp) { - osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount); #ifdef DEBUG osi_assert(vcp->refCount-- != 0); #else vcp->refCount--; #endif + + if (vcp->refCount == 0) { + memset(vcp,0,sizeof(smb_vc_t)); + free(vcp); + } +} + +void smb_ReleaseVCNoLock(smb_vc_t *vcp) +{ + osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount); + smb_ReleaseVCInternal(vcp); } void smb_ReleaseVC(smb_vc_t *vcp) { lock_ObtainWrite(&smb_rctLock); osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount); -#ifdef DEBUG - osi_assert(vcp->refCount-- != 0); -#else - vcp->refCount--; -#endif + smb_ReleaseVCInternal(vcp); lock_ReleaseWrite(&smb_rctLock); } @@ -932,6 +938,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) smb_user_t *userpNext; smb_user_t *userp; unsigned short uid; + smb_vc_t **vcpp; osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp); @@ -997,8 +1004,15 @@ void smb_CleanupDeadVC(smb_vc_t *vcp) lock_ObtainRead(&smb_rctLock); } + /* remove VCP from smb_allVCsp */ + for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) { + if (*vcpp == vcp) { + *vcpp = vcp->nextp; + smb_ReleaseVCNoLock(vcp); + break; + } + } lock_ReleaseRead(&smb_rctLock); - osi_Log0(smb_logp, "Done cleaning up dead vcp"); } @@ -1074,7 +1088,7 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags) uidp = malloc(sizeof(*uidp)); memset(uidp, 0, sizeof(*uidp)); uidp->nextp = vcp->usersp; - uidp->refCount = 1; + uidp->refCount = 2; /* one for the vcp and one for the caller */ uidp->vcp = vcp; smb_HoldVCNoLock(vcp); vcp->usersp = uidp; @@ -1169,7 +1183,7 @@ void smb_ReleaseUID(smb_user_t *uidp) lock_ObtainWrite(&smb_rctLock); osi_assert(uidp->refCount-- > 0); - if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) { + if (uidp->refCount == 0) { lupp = &uidp->vcp->usersp; for(up = *lupp; up; lupp = &up->nextp, up = *lupp) { if (up == uidp) @@ -1195,21 +1209,22 @@ void smb_ReleaseUID(smb_user_t *uidp) cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp) { smb_user_t *uidp; - cm_user_t *up; + cm_user_t *up = NULL; smb_t *smbp; smbp = (smb_t *) inp; uidp = smb_FindUID(vcp, smbp->uid, 0); - if ((!uidp) || (!uidp->unp)) - return NULL; - + if (!uidp) + return NULL; + lock_ObtainMutex(&uidp->mx); - up = uidp->unp->userp; - cm_HoldUser(up); + if (uidp->unp) { + up = uidp->unp->userp; + cm_HoldUser(up); + } lock_ReleaseMutex(&uidp->mx); smb_ReleaseUID(uidp); - return up; } @@ -2425,6 +2440,16 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp) s = "unknown error"; } osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s); + osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x", + vcp, vcp->usersp); + smb_HoldVC(vcp); + if (dead_vcp) { + osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); + smb_CleanupDeadVC(dead_vcp); + smb_ReleaseVC(dead_vcp); + } + dead_vcp = vcp; + vcp->flags |= SMB_VCFLAG_ALREADYDEAD; } if (localNCB) @@ -2979,19 +3004,20 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) ongoingOps - 1); if (!isGateway) { if (active_vcp) { - DWORD now = GetCurrentTime(); - if (now - last_msg_time >= 30000 - && now - last_msg_time <= 90000) { - osi_Log1(smb_logp, - "Setting dead_vcp %x", active_vcp); - if (dead_vcp) { + DWORD now = GetTickCount(); + if (now - last_msg_time >= 30000) { + smb_vc_t *avcp = active_vcp; + active_vcp = NULL; + osi_Log1(smb_logp,"Setting dead_vcp %x", avcp); + if (dead_vcp) { + osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); + smb_CleanupDeadVC(dead_vcp); smb_ReleaseVC(dead_vcp); - osi_Log1(smb_logp, - "Previous dead_vcp %x", dead_vcp); } - smb_HoldVC(active_vcp); - dead_vcp = active_vcp; + smb_HoldVC(avcp); + dead_vcp = avcp; dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + smb_ReleaseVC(avcp); } } } @@ -3983,7 +4009,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) { /* Don't bulk stat if risking timeout */ - int now = GetCurrentTime(); + int now = GetTickCount(); if (now - req.startTime > 5000) { scp->bulkStatProgress = thyper; scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING; @@ -6915,7 +6941,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, /* Remember session generation number and time */ oldGen = sessionGen; - oldTime = GetCurrentTime(); + oldTime = GetTickCount(); while (inp->inCom != 0xff) { dp = &smb_dispatchTable[inp->inCom]; @@ -6979,7 +7005,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, HANDLE h; char *ptbuf[1]; char s[100]; - newTime = GetCurrentTime(); + newTime = GetTickCount(); h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length); @@ -7152,19 +7178,18 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { if (active_vcp != vcp) { if (active_vcp) { - smb_ReleaseVC(active_vcp); osi_Log2(smb_logp, "Replacing active_vcp %x with %x", active_vcp, vcp); + smb_ReleaseVC(active_vcp); } smb_HoldVC(vcp); active_vcp = vcp; } - last_msg_time = GetCurrentTime(); - } else if (active_vcp == vcp) { + last_msg_time = GetTickCount(); + } else if (active_vcp == vcp) { /* the vcp is dead */ smb_ReleaseVC(active_vcp); active_vcp = NULL; } - return; } @@ -7557,39 +7582,30 @@ void smb_Server(VOID *parmp) osi_Log2(smb_logp, "NCBRECV pending lsn %d session %d", ncbp->ncb_lsn, idx_session); continue; - case NRC_SCLOSED: case NRC_SNUMOUT: case NRC_SABORT: + case NRC_SCLOSED: /* Client closed session */ - dead_sessions[idx_session] = TRUE; + dead_sessions[idx_session] = TRUE; if (vcp) smb_ReleaseVC(vcp); vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]); - /* Should also release vcp. [done] 2004-05-11 jaltman - * Also, should do - * sanity check that all TID's are gone. - * - * TODO: check if we could use LSNs[idx_session] instead, - * also cleanup after dead vcp - */ if (vcp) { - if (dead_vcp == vcp) + if (dead_vcp == vcp) osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp); else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x", vcp, vcp->usersp); - smb_HoldVC(vcp); + smb_HoldVC(vcp); if (dead_vcp) { + osi_Log1(smb_logp,"Previous dead_vcp %x", dead_vcp); + smb_CleanupDeadVC(dead_vcp); smb_ReleaseVC(dead_vcp); - osi_Log1(smb_logp, - "Previous dead_vcp %x", dead_vcp); } dead_vcp = vcp; vcp->flags |= SMB_VCFLAG_ALREADYDEAD; } - smb_CleanupDeadVC(vcp); - if (vcp->justLoggedOut) { loggedOut = 1; loggedOutTime = vcp->logoffTime; diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index e5c7ad347..7042dc7db 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -487,6 +487,8 @@ extern void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *dosTimep); extern smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana); +extern void smb_CleanupDeadVC(smb_vc_t *vcp); + extern void smb_ReleaseVC(smb_vc_t *vcp); extern void smb_ReleaseVCNoLock(smb_vc_t *vcp); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index c3e02458e..e79e18212 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -49,7 +49,8 @@ cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp) cm_user_t *up = NULL; uidp = smb_FindUID(vcp, inp->uid, 0); - if (!uidp) return NULL; + if (!uidp) + return NULL; lock_ObtainMutex(&uidp->mx); if (uidp->unp) { @@ -933,7 +934,6 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou /* find the tree and free it */ uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); - /* TODO: smb_ReleaseUID() ? */ if (uidp) { char *s1 = NULL, *s2 = NULL; @@ -951,6 +951,7 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou * because the vcp points to it */ lock_ReleaseMutex(&uidp->mx); + smb_ReleaseUID(uidp); } else osi_Log0(smb_logp, "SMB3 user logoffX"); @@ -1128,7 +1129,8 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp, tp = malloc(sizeof(*tp)); memset(tp, 0, sizeof(*tp)); - tp->vcp = NULL; + smb_HoldVC(vcp); + tp->vcp = vcp; tp->curData = tp->curParms = 0; tp->totalData = totalData; tp->totalParms = totalParms; @@ -4102,7 +4104,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t if ((dsp->flags & SMB_DIRSEARCH_BULKST) && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) { /* Don't bulk stat if risking timeout */ - int now = GetCurrentTime(); + int now = GetTickCount(); if (now - req.startTime > 5000) { scp->bulkStatProgress = thyper; scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING; @@ -6727,6 +6729,8 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp, savedPacketp = smb_CopyPacket(inp); smb_HoldVC(vcp); + if (savedPacketp->vcp) + smb_ReleaseVC(savedPacketp->vcp); savedPacketp->vcp = vcp; lock_ObtainMutex(&smb_Dir_Watch_Lock); savedPacketp->nextp = smb_Directory_Watches; @@ -6884,7 +6888,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter, BOOL twoEntries = FALSE; ULONG otherNameLen, oldParmCount = 0; DWORD otherAction; - smb_vc_t *vcp; smb_fid_t *fidp; /* Get ready for rename within directory */ @@ -6905,7 +6908,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter, wtree = smb_GetSMBParm(watch, 22) & 0xffff; /* TODO: should this be 0xff ? */ maxLen = smb_GetSMBOffsetParm(watch, 5, 1) | (smb_GetSMBOffsetParm(watch, 6, 1) << 16); - vcp = watch->vcp; /* * Strange hack - bug in NT Client and NT Server that we @@ -6914,7 +6916,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter, if (filter == 3 && wtree) filter = 0x17; - fidp = smb_FindFID(vcp, fid, 0); + fidp = smb_FindFID(watch->vcp, fid, 0); if (!fidp) { osi_Log1(smb_logp," no fidp for fid[%d]",fid); lastWatch = watch; @@ -7044,7 +7046,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter, ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS; } - smb_SendPacket(vcp, watch); + smb_SendPacket(watch->vcp, watch); smb_FreePacket(watch); watch = nextWatch; } diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 072bb1fcc..f1828f9c9 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -31,59 +31,59 @@ smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS]; void smb_InitIoctl(void) { - int i; - for (i=0; iinAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA); - if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA); - - /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */ - (void) memset(ioctlp->inAllocp, 0, SMB_IOCTL_MAXDATA); - (void) memset(ioctlp->outAllocp, 0, SMB_IOCTL_MAXDATA); - - /* and make sure that we've reset our state for the new incoming request */ - if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) { - ioctlp->inCopied = 0; - ioctlp->outCopied = 0; - ioctlp->inDatap = ioctlp->inAllocp; - ioctlp->outDatap = ioctlp->outAllocp; - ioctlp->flags |= SMB_IOCTLFLAG_DATAIN; - } -} + /* make sure the buffer(s) are allocated */ + if (!ioctlp->inAllocp) ioctlp->inAllocp = malloc(SMB_IOCTL_MAXDATA); + if (!ioctlp->outAllocp) ioctlp->outAllocp = malloc(SMB_IOCTL_MAXDATA); + + /* Fixes fs la problem. We do a StrToOEM later and if this data isn't initialized we get memory issues. */ + (void) memset(ioctlp->inAllocp, 0, SMB_IOCTL_MAXDATA); + (void) memset(ioctlp->outAllocp, 0, SMB_IOCTL_MAXDATA); + + /* and make sure that we've reset our state for the new incoming request */ + if (!(ioctlp->flags & SMB_IOCTLFLAG_DATAIN)) { + ioctlp->inCopied = 0; + ioctlp->outCopied = 0; + ioctlp->inDatap = ioctlp->inAllocp; + ioctlp->outDatap = ioctlp->outAllocp; + ioctlp->flags |= SMB_IOCTLFLAG_DATAIN; + } +} /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, - smb_packet_t *outp) + smb_packet_t *outp) { - smb_ioctl_t *iop; - long count; - long leftToCopy; - char *op; - long code; - cm_user_t *userp; - - iop = fidp->ioctlp; - count = smb_GetSMBParm(inp, 1); - userp = smb_GetUser(vcp, inp); - - /* Identify tree */ + smb_ioctl_t *iop; + long count; + long leftToCopy; + char *op; + long code; + cm_user_t *userp; + + iop = fidp->ioctlp; + count = smb_GetSMBParm(inp, 1); + userp = smb_GetUser(vcp, inp); + + /* Identify tree */ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); - if(code) { + if (code) { cm_ReleaseUser(userp); return CM_ERROR_NOSUCHPATH; } - /* turn the connection around, if required */ - code = smb_IoctlPrepareRead(fidp, iop, userp); + /* turn the connection around, if required */ + code = smb_IoctlPrepareRead(fidp, iop, userp); - if (code) { - cm_ReleaseUser(userp); - return code; - } + if (code) { + cm_ReleaseUser(userp); + return code; + } - leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; - if (count > leftToCopy) count = leftToCopy; - - /* now set the parms for a read of count bytes */ - smb_SetSMBParm(outp, 0, count); - smb_SetSMBParm(outp, 1, 0); - smb_SetSMBParm(outp, 2, 0); - smb_SetSMBParm(outp, 3, 0); - smb_SetSMBParm(outp, 4, 0); - - smb_SetSMBDataLength(outp, count+3); - - op = smb_GetSMBData(outp, NULL); - *op++ = 1; - *op++ = (char)(count & 0xff); - *op++ = (char)((count >> 8) & 0xff); - - /* now copy the data into the response packet */ - memcpy(op, iop->outCopied + iop->outAllocp, count); + leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; + if (count > leftToCopy) count = leftToCopy; - /* and adjust the counters */ - iop->outCopied += count; - - cm_ReleaseUser(userp); - smb_ReleaseFID(fidp); + /* now set the parms for a read of count bytes */ + smb_SetSMBParm(outp, 0, count); + smb_SetSMBParm(outp, 1, 0); + smb_SetSMBParm(outp, 2, 0); + smb_SetSMBParm(outp, 3, 0); + smb_SetSMBParm(outp, 4, 0); - return 0; -} + smb_SetSMBDataLength(outp, count+3); + + op = smb_GetSMBData(outp, NULL); + *op++ = 1; + *op++ = (char)(count & 0xff); + *op++ = (char)((count >> 8) & 0xff); + + /* now copy the data into the response packet */ + memcpy(op, iop->outCopied + iop->outAllocp, count); + + /* and adjust the counters */ + iop->outCopied += count; + + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); + + return 0; +} /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL * file descriptor. */ long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_ioctl_t *iop; - long count; - long code; - char *op; - int inDataBlockCount; - - code = 0; - count = smb_GetSMBParm(inp, 1); - iop = fidp->ioctlp; - - smb_IoctlPrepareWrite(fidp, iop); + smb_ioctl_t *iop; + long count; + long code; + char *op; + int inDataBlockCount; - op = smb_GetSMBData(inp, NULL); - op = smb_ParseDataBlock(op, NULL, &inDataBlockCount); - - if (count + iop->inCopied > SMB_IOCTL_MAXDATA) { - code = CM_ERROR_TOOBIG; - goto done; - } + code = 0; + count = smb_GetSMBParm(inp, 1); + iop = fidp->ioctlp; - /* copy data */ - memcpy(iop->inDatap + iop->inCopied, op, count); + smb_IoctlPrepareWrite(fidp, iop); + + op = smb_GetSMBData(inp, NULL); + op = smb_ParseDataBlock(op, NULL, &inDataBlockCount); + + if (count + iop->inCopied > SMB_IOCTL_MAXDATA) { + code = CM_ERROR_TOOBIG; + goto done; + } - /* adjust counts */ - iop->inCopied += count; + /* copy data */ + memcpy(iop->inDatap + iop->inCopied, op, count); -done: - /* return # of bytes written */ - if (code == 0) { - smb_SetSMBParm(outp, 0, count); - smb_SetSMBDataLength(outp, 0); - } + /* adjust counts */ + iop->inCopied += count; - smb_ReleaseFID(fidp); - return code; + done: + /* return # of bytes written */ + if (code == 0) { + smb_SetSMBParm(outp, 0, count); + smb_SetSMBDataLength(outp, 0); + } + + smb_ReleaseFID(fidp); + return code; } /* called from V3 read to handle IOCTL descriptor reads */ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_ioctl_t *iop; + smb_ioctl_t *iop; long count; long code; long leftToCopy; @@ -292,82 +292,83 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack iop = fidp->ioctlp; count = smb_GetSMBParm(inp, 5); - userp = smb_GetUser(vcp, inp); - osi_assert(userp != 0); + userp = smb_GetUser(vcp, inp); + osi_assert(userp != 0); uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); iop->uidp = uidp; - if (uidp && uidp->unp) + if (uidp && uidp->unp) { osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", - uidp->userID, userp, - osi_LogSaveString(afsd_logp, uidp->unp->name)); - else { + uidp->userID, userp, + osi_LogSaveString(afsd_logp, uidp->unp->name)); + } else { if (uidp) - osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", - uidp->userID, userp); + osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", + uidp->userID, userp); else - osi_Log1(afsd_logp, "Ioctl no uid user %x no name", - userp); + osi_Log1(afsd_logp, "Ioctl no uid user %x no name", + userp); } - code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); - if(code) { - smb_ReleaseUID(uidp); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); + if (code) { + if (uidp) + smb_ReleaseUID(uidp); cm_ReleaseUser(userp); smb_ReleaseFID(fidp); return CM_ERROR_NOSUCHPATH; } - code = smb_IoctlPrepareRead(fidp, iop, userp); + code = smb_IoctlPrepareRead(fidp, iop, userp); if (uidp) { iop->uidp = 0; smb_ReleaseUID(uidp); } if (code) { - cm_ReleaseUser(userp); + cm_ReleaseUser(userp); smb_ReleaseFID(fidp); - return code; + return code; } - leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; + leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; if (count > leftToCopy) count = leftToCopy; - /* 0 and 1 are reserved for request chaining, were setup by our caller, - * and will be further filled in after we return. - */ - smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */ - smb_SetSMBParm(outp, 3, 0); /* resvd */ - smb_SetSMBParm(outp, 4, 0); /* resvd */ - smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */ - /* fill in #6 when we have all the parameters' space reserved */ - smb_SetSMBParm(outp, 7, 0); /* resv'd */ - smb_SetSMBParm(outp, 8, 0); /* resv'd */ - smb_SetSMBParm(outp, 9, 0); /* resv'd */ - smb_SetSMBParm(outp, 10, 0); /* resv'd */ - smb_SetSMBParm(outp, 11, 0); /* reserved */ - - /* get op ptr after putting in the last parm, since otherwise we don't - * know where the data really is. - */ - op = smb_GetSMBData(outp, NULL); - - /* now fill in offset from start of SMB header to first data byte (to op) */ - smb_SetSMBParm(outp, 6, ((int) (op - outp->data))); - - /* set the packet data length the count of the # of bytes */ - smb_SetSMBDataLength(outp, count); - - /* now copy the data into the response packet */ - memcpy(op, iop->outCopied + iop->outAllocp, count); - - /* and adjust the counters */ - iop->outCopied += count; - - /* and cleanup things */ - cm_ReleaseUser(userp); - smb_ReleaseFID(fidp); + /* 0 and 1 are reserved for request chaining, were setup by our caller, + * and will be further filled in after we return. + */ + smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */ + smb_SetSMBParm(outp, 3, 0); /* resvd */ + smb_SetSMBParm(outp, 4, 0); /* resvd */ + smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */ + /* fill in #6 when we have all the parameters' space reserved */ + smb_SetSMBParm(outp, 7, 0); /* resv'd */ + smb_SetSMBParm(outp, 8, 0); /* resv'd */ + smb_SetSMBParm(outp, 9, 0); /* resv'd */ + smb_SetSMBParm(outp, 10, 0); /* resv'd */ + smb_SetSMBParm(outp, 11, 0); /* reserved */ + + /* get op ptr after putting in the last parm, since otherwise we don't + * know where the data really is. + */ + op = smb_GetSMBData(outp, NULL); + + /* now fill in offset from start of SMB header to first data byte (to op) */ + smb_SetSMBParm(outp, 6, ((int) (op - outp->data))); + + /* set the packet data length the count of the # of bytes */ + smb_SetSMBDataLength(outp, count); + + /* now copy the data into the response packet */ + memcpy(op, iop->outCopied + iop->outAllocp, count); + + /* and adjust the counters */ + iop->outCopied += count; + + /* and cleanup things */ + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); - return 0; + return 0; } /* called from Read Raw to handle IOCTL descriptor reads */ @@ -378,41 +379,44 @@ long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, #endif /* DJGPP */ ) { - smb_ioctl_t *iop; - long leftToCopy; - NCB *ncbp; - long code; - cm_user_t *userp; + smb_ioctl_t *iop; + long leftToCopy; + NCB *ncbp; + long code; + cm_user_t *userp; #ifdef DJGPP - dos_ptr dos_ncb; + dos_ptr dos_ncb; - if (rawBuf == 0) - { - osi_Log0(afsd_logp, "Failed to get raw buf for smb_IoctlReadRaw"); - return -1; - } + if (rawBuf == 0) + { + osi_Log0(afsd_logp, "Failed to get raw buf for smb_IoctlReadRaw"); + return -1; + } #endif /* DJGPP */ - iop = fidp->ioctlp; - - userp = smb_GetUser(vcp, inp); - - { - smb_user_t *uidp; - - uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); - if (uidp && uidp->unp) - osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", - uidp->userID, userp, - osi_LogSaveString(afsd_logp, uidp->unp->name)); - else if (uidp) - osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", - uidp->userID, userp); - else - osi_Log1(afsd_logp, "Ioctl no uid user %x no name", - userp); - if (uidp) smb_ReleaseUID(uidp); + iop = fidp->ioctlp; + + userp = smb_GetUser(vcp, inp); + + /* Log the user */ + { + smb_user_t *uidp; + + uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); + if (uidp && uidp->unp) { + osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s", + uidp->userID, userp, + osi_LogSaveString(afsd_logp, uidp->unp->name)); + } else if (uidp) { + osi_Log2(afsd_logp, "Ioctl uid %d user %x no name", + uidp->userID, userp); + } else { + osi_Log1(afsd_logp, "Ioctl no uid user %x no name", + userp); } + if (uidp) + smb_ReleaseUID(uidp); + } code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); if(code) { @@ -421,39 +425,39 @@ long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, return CM_ERROR_NOSUCHPATH; } - code = smb_IoctlPrepareRead(fidp, iop, userp); - if (code) { - cm_ReleaseUser(userp); - smb_ReleaseFID(fidp); - return code; - } + code = smb_IoctlPrepareRead(fidp, iop, userp); + if (code) { + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); + return code; + } - leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; + leftToCopy = (iop->outDatap - iop->outAllocp) - iop->outCopied; - ncbp = outp->ncbp; - memset((char *)ncbp, 0, sizeof(NCB)); + ncbp = outp->ncbp; + memset((char *)ncbp, 0, sizeof(NCB)); - ncbp->ncb_length = (unsigned short) leftToCopy; - ncbp->ncb_lsn = (unsigned char) vcp->lsn; - ncbp->ncb_command = NCBSEND; + ncbp->ncb_length = (unsigned short) leftToCopy; + ncbp->ncb_lsn = (unsigned char) vcp->lsn; + ncbp->ncb_command = NCBSEND; /*ncbp->ncb_lana_num = smb_LANadapter;*/ - ncbp->ncb_lana_num = vcp->lana; + ncbp->ncb_lana_num = vcp->lana; #ifndef DJGPP - ncbp->ncb_buffer = iop->outCopied + iop->outAllocp; - code = Netbios(ncbp); + ncbp->ncb_buffer = iop->outCopied + iop->outAllocp; + code = Netbios(ncbp); #else /* DJGPP */ - dosmemput(iop->outCopied + iop->outAllocp, ncbp->ncb_length, rawBuf); - ncbp->ncb_buffer = rawBuf; - dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb; - code = Netbios(ncbp, dos_ncb); + dosmemput(iop->outCopied + iop->outAllocp, ncbp->ncb_length, rawBuf); + ncbp->ncb_buffer = rawBuf; + dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb; + code = Netbios(ncbp, dos_ncb); #endif /* !DJGPP */ - if (code != 0) - osi_Log1(afsd_logp, "ReadRaw send failure code %d", code); + if (code != 0) + osi_Log1(afsd_logp, "ReadRaw send failure code %d", code); - cm_ReleaseUser(userp); - smb_ReleaseFID(fidp); + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); - return 0; + return 0; } -- 2.39.5