#pragma warning(disable: 4005)
#include <ntstatus.h>
#pragma warning(pop)
+#include <sddl.h>
#include <stddef.h>
#include <stdlib.h>
#include <malloc.h>
#include <WINNT\afsreg.h>
#include "smb.h"
+#include "msrpc.h"
#include "lanahelper.h"
#define STRSAFE_NO_DEPRECATE
smb_dirSearch_t *smb_firstDirSearchp;
smb_dirSearch_t *smb_lastDirSearchp;
+/* Initial mode bits for files and directories. Set to 0 to use
+ defaults. */
+int smb_unixModeDefaultFile = 0666;
+int smb_unixModeDefaultDir = 0777;
+
/* hide dot files? */
int smb_hideDotFiles;
*/
time_t smb_localZero = 0;
-#define USE_NUMERIC_TIME_CONV 1
-
-#ifndef USE_NUMERIC_TIME_CONV
-/* Time difference for converting to kludge-GMT */
-afs_uint32 smb_NowTZ;
-#endif /* USE_NUMERIC_TIME_CONV */
-
char *smb_localNamep = NULL;
smb_vc_t *smb_allVCsp;
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);
reqp->flags |= CM_REQ_SOURCE_SMB;
}
-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 = TlsGetValue(smb_TlsRequestSlot);
- if (!tp)
- 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(), (int)((now - *tp) / 15));
- }
-}
-
-
const char * ncb_error_string(int code)
{
const char * s;
switch ( code ) {
- case 0x01: s = "llegal buffer length"; break;
- case 0x03: s = "illegal command"; break;
- case 0x05: s = "command timed out"; break;
- case 0x06: s = "message incomplete, issue another command"; break;
- case 0x07: s = "illegal buffer address"; break;
- case 0x08: s = "session number out of range"; break;
- case 0x09: s = "no resource available"; break;
- case 0x0a: s = "session closed"; break;
- case 0x0b: s = "command cancelled"; break;
- case 0x0d: s = "duplicate name"; break;
- case 0x0e: s = "name table full"; break;
- case 0x0f: s = "no deletions, name has active sessions"; break;
- case 0x11: s = "local session table full"; break;
- case 0x12: s = "remote session table full"; break;
- case 0x13: s = "illegal name number"; break;
- case 0x14: s = "no callname"; break;
- case 0x15: s = "cannot put * in NCB_NAME"; break;
- case 0x16: s = "name in use on remote adapter"; break;
- case 0x17: s = "name deleted"; break;
- case 0x18: s = "session ended abnormally"; break;
- case 0x19: s = "name conflict detected"; break;
- case 0x21: s = "interface busy, IRET before retrying"; break;
- case 0x22: s = "too many commands outstanding, retry later";break;
- case 0x23: s = "ncb_lana_num field invalid"; break;
- case 0x24: s = "command completed while cancel occurring "; break;
- case 0x26: s = "command not valid to cancel"; break;
- case 0x30: s = "name defined by anther local process"; break;
- case 0x34: s = "environment undefined. RESET required"; break;
- case 0x35: s = "required OS resources exhausted"; break;
- case 0x36: s = "max number of applications exceeded"; break;
- case 0x37: s = "no saps available for netbios"; break;
- case 0x38: s = "requested resources are not available"; break;
- case 0x39: s = "invalid ncb address or length > segment"; break;
- case 0x3B: s = "invalid NCB DDID"; break;
- case 0x3C: s = "lock of user area failed"; break;
- case 0x3f: s = "NETBIOS not loaded"; break;
- case 0x40: s = "system error"; break;
+ case 0x01: s = "NRC_BUFLEN llegal buffer length"; break;
+ case 0x03: s = "NRC_ILLCMD illegal command"; break;
+ case 0x05: s = "NRC_CMDTMO command timed out"; break;
+ case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break;
+ case 0x07: s = "NRC_BADDR illegal buffer address"; break;
+ case 0x08: s = "NRC_SNUMOUT session number out of range"; break;
+ case 0x09: s = "NRC_NORES no resource available"; break;
+ case 0x0a: s = "NRC_SCLOSED asession closed"; break;
+ case 0x0b: s = "NRC_CMDCAN command cancelled"; break;
+ case 0x0d: s = "NRC_DUPNAME duplicate name"; break;
+ case 0x0e: s = "NRC_NAMTFUL name table full"; break;
+ case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break;
+ case 0x11: s = "NRC_LOCTFUL local session table full"; break;
+ case 0x12: s = "NRC_REMTFUL remote session table full"; break;
+ case 0x13: s = "NRC_ILLNN illegal name number"; break;
+ case 0x14: s = "NRC_NOCALL no callname"; break;
+ case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME"; break;
+ case 0x16: s = "NRC_INUSE name in use on remote adapter"; break;
+ case 0x17: s = "NRC_NAMERR name deleted"; break;
+ case 0x18: s = "NRC_SABORT session ended abnormally"; break;
+ case 0x19: s = "NRC_NAMCONF name conflict detected"; break;
+ case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying"; break;
+ case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
+ case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid"; break;
+ case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break;
+ case 0x26: s = "NRC_CANCEL command not valid to cancel"; break;
+ case 0x30: s = "NRC_DUPENV name defined by anther local process"; break;
+ case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required"; break;
+ case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted"; break;
+ case 0x36: s = "NRC_MAXAPPS max number of applications exceeded"; break;
+ case 0x37: s = "NRC_NOSAPS no saps available for netbios"; break;
+ case 0x38: s = "NRC_NORESOURCES requested resources are not available"; break;
+ case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment"; break;
+ case 0x3B: s = "NRC_INVDDID invalid NCB DDID"; break;
+ case 0x3C: s = "NRC_LOCKFAILlock of user area failed"; break;
+ case 0x3f: s = "NRC_OPENERR NETBIOS not loaded"; break;
+ case 0x40: s = "NRC_SYSTEM system error"; break;
default: s = "unknown error";
}
return s;
case 63:
return "RAP(63)NetWkStaGetInfo";
}
-}
+}
+
+char * myCrt_NmpipeDispatch(int i)
+{
+ switch(i) {
+ case SMB_TRANS_SET_NMPIPE_STATE:
+ return "SET NMPIPE STATE";
+
+ case SMB_TRANS_RAW_READ_NMPIPE:
+ return "RAW READ NMPIPE";
+
+ case SMB_TRANS_QUERY_NMPIPE_STATE:
+ return "QUERY NMPIPE STATE";
+
+ case SMB_TRANS_QUERY_NMPIPE_INFO:
+ return "QUERY NMPIPE INFO";
+
+ case SMB_TRANS_PEEK_NMPIPE:
+ return "PEEK NMPIPE";
+
+ case SMB_TRANS_TRANSACT_NMPIPE:
+ return "TRANSACT NMPIPE";
+
+ case SMB_TRANS_RAW_WRITE_NMPIPE:
+ return "WRITE NMPIPE";
+
+ case SMB_TRANS_READ_NMPIPE:
+ return "READ NMPIPE";
+
+ case SMB_TRANS_WRITE_NMPIPE:
+ return "WRITE NMPIPE";
+
+ case SMB_TRANS_WAIT_NMPIPE:
+ return "WAIT NMPIPE";
+
+ case SMB_TRANS_CALL_NMPIPE:
+ return "CALL NMPIPE";
+ }
+ return "(Unknown)";
+}
/* scache must be locked */
unsigned int smb_Attributes(cm_scache_t *scp)
* turns out to be impolitic in NT. See defect 10007.
*/
#ifdef notdef
- if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
#else
- if ((scp->unixModeBits & 0222) == 0)
+ if ((scp->unixModeBits & 0200) == 0)
attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
#endif
return attrs;
}
+void smb_SetInitialModeBitsForFile(int smb_attr, cm_attr_t * attr)
+{
+ if (smb_unixModeDefaultFile != 0) {
+ attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
+ attr->unixModeBits = smb_unixModeDefaultFile;
+ if (smb_attr & SMB_ATTR_READONLY)
+ attr->unixModeBits &= ~0222;
+ }
+}
+
+void smb_SetInitialModeBitsForDir(int smb_attr, cm_attr_t * attr)
+{
+ if (smb_unixModeDefaultDir != 0) {
+ attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
+ attr->unixModeBits = smb_unixModeDefaultDir;
+ }
+}
+
/* Check if the named file/dir is a dotfile/dotdir */
/* String pointed to by lastComp can have leading slashes, but otherwise should have
no other patch components */
FILETIME ft;
WORD wDate, wTime;
- smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, unixTime);
if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
*pLastWriteTime -= (-bias * 60); /* Convert bias to seconds */
}
-#ifndef USE_NUMERIC_TIME_CONV
-/*
- * Calculate the difference (in seconds) between local time and GMT.
- * This enables us to convert file times to kludge-GMT.
- */
-static void
-smb_CalculateNowTZ()
+void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
{
- time_t t;
- struct tm gmt_tm, local_tm;
- int days, hours, minutes, seconds;
-
- t = time(NULL);
- gmt_tm = *(gmtime(&t));
- local_tm = *(localtime(&t));
-
- days = local_tm.tm_yday - gmt_tm.tm_yday;
- hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
- minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
- seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
-
- smb_NowTZ = seconds;
+ time_t diff_t = unixTime - smb_localZero;
+#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
+ osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
+#endif
+ *dosUTimep = (afs_uint32)diff_t;
}
-#endif /* USE_NUMERIC_TIME_CONV */
-#ifdef USE_NUMERIC_TIME_CONV
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
{
- // Note that LONGLONG is a 64-bit value
- LONGLONG ll;
-
- ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
- largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
- largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
+ *unixTimep = dosTime + smb_localZero;
}
-#else
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+
+void smb_MarkAllVCsDead(smb_vc_t * exclude)
{
- struct tm *ltp;
- SYSTEMTIME stm;
- struct tm localJunk;
- time_t ersatz_unixTime;
+ smb_vc_t *vcp;
+ smb_vc_t **vcp_to_cleanup = NULL;
+ int n_to_cleanup = 0;
+ int i;
- /*
- * Must use kludge-GMT instead of real GMT.
- * kludge-GMT is computed by adding time zone difference to localtime.
- *
- * real GMT would be:
- * ltp = gmtime(&unixTime);
- */
- ersatz_unixTime = unixTime - smb_NowTZ;
- ltp = localtime(&ersatz_unixTime);
-
- /* if we fail, make up something */
- if (!ltp) {
- ltp = &localJunk;
- localJunk.tm_year = 89 - 20;
- localJunk.tm_mon = 4;
- localJunk.tm_mday = 12;
- localJunk.tm_hour = 0;
- localJunk.tm_min = 0;
- localJunk.tm_sec = 0;
- }
-
- stm.wYear = ltp->tm_year + 1900;
- stm.wMonth = ltp->tm_mon + 1;
- stm.wDayOfWeek = ltp->tm_wday;
- stm.wDay = ltp->tm_mday;
- stm.wHour = ltp->tm_hour;
- stm.wMinute = ltp->tm_min;
- stm.wSecond = ltp->tm_sec;
- stm.wMilliseconds = 0;
-
- SystemTimeToFileTime(&stm, largeTimep);
-}
-#endif /* USE_NUMERIC_TIME_CONV */
+ osi_Log1(smb_logp, "Marking all VCs as dead excluding %p", exclude);
-#ifdef USE_NUMERIC_TIME_CONV
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
- // Note that LONGLONG is a 64-bit value
- LONGLONG ll;
+ lock_ObtainWrite(&smb_globalLock); /* for dead_sessions[] */
+ lock_ObtainWrite(&smb_rctLock);
+ for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
- ll = largeTimep->dwHighDateTime;
- ll <<= 32;
- ll += largeTimep->dwLowDateTime;
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
- ll -= 116444736000000000;
- ll /= 10000000;
+ if (vcp == exclude)
+ continue;
- *unixTimep = (DWORD)ll;
-}
-#else /* USE_NUMERIC_TIME_CONV */
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
- SYSTEMTIME stm;
- struct tm lt;
- long save_timezone;
-
- FileTimeToSystemTime(largeTimep, &stm);
-
- lt.tm_year = stm.wYear - 1900;
- lt.tm_mon = stm.wMonth - 1;
- lt.tm_wday = stm.wDayOfWeek;
- lt.tm_mday = stm.wDay;
- lt.tm_hour = stm.wHour;
- lt.tm_min = stm.wMinute;
- lt.tm_sec = stm.wSecond;
- lt.tm_isdst = -1;
-
- save_timezone = _timezone;
- _timezone += smb_NowTZ;
- *unixTimep = mktime(<);
- _timezone = save_timezone;
-}
-#endif /* USE_NUMERIC_TIME_CONV */
-
-void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
-{
- struct tm *ltp;
- int dosDate;
- int dosTime;
- struct tm localJunk;
- time_t t = unixTime;
-
- ltp = localtime(&t);
-
- /* if we fail, make up something */
- if (!ltp) {
- ltp = &localJunk;
- localJunk.tm_year = 89 - 20;
- localJunk.tm_mon = 4;
- localJunk.tm_mday = 12;
- localJunk.tm_hour = 0;
- localJunk.tm_min = 0;
- localJunk.tm_sec = 0;
- }
+ lock_ObtainMutex(&vcp->mx);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ dead_sessions[vcp->session] = TRUE;
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
+ n_to_cleanup ++;
+ }
- dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
- dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
- *searchTimep = (dosDate<<16) | dosTime;
-}
+ vcp_to_cleanup = malloc(sizeof(vcp_to_cleanup[0]) * n_to_cleanup);
+ i = 0;
+ for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
+ if (vcp == exclude)
+ continue;
-void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
-{
- unsigned short dosDate;
- unsigned short dosTime;
- struct tm localTm;
-
- dosDate = (unsigned short) (searchTime & 0xffff);
- dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
-
- localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
- localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
- localTm.tm_mday = (dosDate) & 0x1f;
- localTm.tm_hour = (dosTime>>11) & 0x1f;
- localTm.tm_min = (dosTime >> 5) & 0x3f;
- localTm.tm_sec = (dosTime & 0x1f) * 2;
- localTm.tm_isdst = -1; /* compute whether DST in effect */
-
- *unixTimep = mktime(&localTm);
-}
+ vcp_to_cleanup[i++] = vcp;
+ smb_HoldVCNoLock(vcp);
+ }
-void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
-{
- time_t diff_t = unixTime - smb_localZero;
-#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
- osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
-#endif
- *dosUTimep = (afs_uint32)diff_t;
-}
+ osi_assert(i == n_to_cleanup);
-void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
-{
- *unixTimep = dosTime + smb_localZero;
+ lock_ReleaseWrite(&smb_rctLock);
+ lock_ReleaseWrite(&smb_globalLock);
+
+ for (i=0; i < n_to_cleanup; i++) {
+ smb_CleanupDeadVC(vcp_to_cleanup[i]);
+ smb_ReleaseVC(vcp_to_cleanup[i]);
+ vcp_to_cleanup[i] = 0;
+ }
+
+ free(vcp_to_cleanup);
}
#ifdef DEBUG_SMB_REFCOUNT
osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
__FILE__, __LINE__);
+ lock_ObtainMutex(&vcp->mx);
if (lsn == vcp->lsn && lana == vcp->lana &&
!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ lock_ReleaseMutex(&vcp->mx);
smb_HoldVCNoLock(vcp);
break;
}
+ lock_ReleaseMutex(&vcp->mx);
}
if (!vcp && (flags & SMB_FLAG_CREATE)) {
vcp = malloc(sizeof(*vcp));
vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
vcp->nextp = smb_allVCsp;
smb_allVCsp = vcp;
- lock_InitializeMutex(&vcp->mx, "vc_t mutex");
+ lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
vcp->lsn = lsn;
vcp->lana = lana;
vcp->secCtx = NULL;
if (ntsEx == STATUS_SUCCESS) {
memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
- LsaFreeReturnBuffer(lsaResp);
} else {
/*
* This will cause the subsequent authentication to fail but
*/
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
}
+ if (lsaResp)
+ LsaFreeReturnBuffer(lsaResp);
}
else
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
return vcp;
}
-int smb_IsStarMask(clientchar_t *maskp)
+static int smb_Is8Dot3StarMask(clientchar_t *maskp)
{
int i;
clientchar_t tc;
return 0;
}
+static int smb_IsStarMask(clientchar_t *maskp)
+{
+ clientchar_t tc;
+
+ while (*maskp) {
+ tc = *maskp++;
+ if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
+ return 1;
+ }
+ return 0;
+}
+
#ifdef DEBUG_SMB_REFCOUNT
void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
#define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
tidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
vcp->tidsp = tidp;
- lock_InitializeMutex(&tidp->mx, "tid_t mutex");
+ lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
tidp->tid = tid;
}
#ifdef DEBUG_SMB_REFCOUNT
free(tidp);
}
}
+ if (vcp)
+ smb_ReleaseVCNoLock(vcp);
if (!locked)
lock_ReleaseWrite(&smb_rctLock);
if (userp)
cm_ReleaseUser(userp);
- if (vcp)
- smb_ReleaseVCNoLock(vcp);
}
smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
uidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
vcp->usersp = uidp;
- lock_InitializeMutex(&uidp->mx, "user_t mutex");
+ lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
uidp->userID = uid;
osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
vcp, uidp->userID,
return uidp;
}
+afs_int32 smb_userIsLocalSystem(smb_user_t *uidp)
+{
+ SID *pSid = NULL;
+ DWORD dwSize1 = 0, dwSize2 = 0;
+ wchar_t *pszRefDomain = NULL;
+ SID_NAME_USE snu = SidTypeGroup;
+ clientchar_t * secSidString = NULL;
+ DWORD gle;
+ afs_int32 isSystem = 0;
+
+ if (uidp->unp->flags & SMB_USERNAMEFLAG_SID) {
+ isSystem = !cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, uidp->unp->name);
+ return isSystem;
+ }
+
+ /*
+ * The input name is not a SID for the user. See if we can
+ * obtain the SID for the specified name. If we can, use
+ * that instead of the name provided for the comparison.
+ */
+
+ LookupAccountNameW( NULL /* System Name to begin Search */,
+ uidp->unp->name,
+ NULL, &dwSize1,
+ NULL, &dwSize2,
+ &snu);
+ gle = GetLastError();
+ if (gle == ERROR_INSUFFICIENT_BUFFER) {
+ pSid = malloc(dwSize1);
+ /*
+ * Although dwSize2 is supposed to include the terminating
+ * NUL character, on Win7 it does not.
+ */
+ pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
+ }
+
+ if ( pSid && pszRefDomain ) {
+ memset(pSid, 0, dwSize1);
+
+ if (LookupAccountNameW( NULL /* System Name to begin Search */,
+ uidp->unp->name,
+ pSid, &dwSize1,
+ pszRefDomain, &dwSize2,
+ &snu))
+ ConvertSidToStringSidW(pSid, &secSidString);
+ }
+
+ if (secSidString) {
+ isSystem = !cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, secSidString);
+ LocalFree(secSidString);
+ }
+
+ if (pSid)
+ free(pSid);
+ if (pszRefDomain)
+ free(pszRefDomain);
+
+ return isSystem;
+}
+
smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
afs_uint32 flags)
{
unp->name = cm_ClientStrDup(usern);
unp->machine = cm_ClientStrDup(machine);
usernamesp = unp;
- lock_InitializeMutex(&unp->mx, "username_t mutex");
+ lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
if (flags & SMB_FLAG_AFSLOGON)
unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
}
smb_fid_t *fidp;
int newFid = 0;
- if (fid == 0 && !(flags & SMB_FLAG_CREATE))
- return NULL;
-
- lock_ObtainWrite(&smb_rctLock);
- /* figure out if we need to allocate a new file ID */
if (fid == 0) {
+ if (!(flags & SMB_FLAG_CREATE))
+ return NULL;
newFid = 1;
- fid = vcp->fidCounter;
}
+ lock_ObtainWrite(&smb_rctLock);
+ if (newFid)
+ fid = vcp->fidCounter;
retry:
+
for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
if (fidp->refCount == 0 && fidp->deleteOk) {
fidp->refCount++;
lock_ReleaseWrite(&smb_rctLock);
smb_ReleaseFID(fidp);
lock_ObtainWrite(&smb_rctLock);
+ /*
+ * We dropped the smb_rctLock so the fid value we are using
+ * may now be used by another thread. Start over with the
+ * current vcp->fidCounter.
+ */
+ if (newFid)
+ fid = vcp->fidCounter;
goto retry;
}
if (fid == fidp->fid) {
if (newFid) {
+ osi_Log1(smb_logp, "smb_FindFID New Fid Requested. fid %d found -- retrying ...", fid);
fid++;
if (fid == 0xFFFF) {
osi_Log1(smb_logp,
if (!fidp && (flags & SMB_FLAG_CREATE)) {
char eventName[MAX_PATH];
EVENT_HANDLE event;
+
+ if (!newFid)
+ osi_Log1(smb_logp, "smb_FindFID New Fid Not Requested, Fid %d Not Found and CREATE flag set.", fid);
+ else
+ osi_Log1(smb_logp, "smb_FindFID New Fid Requested. Creating fid %d", fid);
+
sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
fidp->refCount = 1;
fidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
- lock_InitializeMutex(&fidp->mx, "fid_t mutex");
+ lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
fidp->fid = fid;
fidp->curr_chunk = fidp->prev_chunk = -2;
fidp->raw_write_event = event;
return fidp;
}
+
+/* Must not be called with scp->rw held because smb_ReleaseFID might be called */
#ifdef DEBUG_SMB_REFCOUNT
smb_fid_t *smb_FindFIDByScacheDbg(smb_vc_t *vcp, cm_scache_t * scp, char *file, long line)
#else
smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
#endif
{
- smb_fid_t *fidp = NULL;
- int newFid = 0;
+ smb_fid_t *fidp = NULL, *nextp = NULL;
if (!scp)
return NULL;
+ /*
+ * If the fidp->scp changes out from under us then
+ * we must not grab a refCount. It means the *fidp
+ * was processed by smb_CloseFID() and the *fidp is
+ * no longer valid for use.
+ */
lock_ObtainWrite(&smb_rctLock);
- for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+ for(fidp = vcp->fidsp, (fidp ? fidp->refCount++ : 0); fidp; fidp = nextp, nextp = NULL) {
+ nextp = (smb_fid_t *) osi_QNext(&fidp->q);
+ if (nextp)
+ nextp->refCount++;
+
if (scp == fidp->scp) {
- fidp->refCount++;
- break;
+ lock_ReleaseWrite(&smb_rctLock);
+ lock_ObtainMutex(&fidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
+ if (scp == fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ break;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+ }
+
+ if (fidp->refCount > 1) {
+ fidp->refCount--;
+ } else {
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_ReleaseFID(fidp);
+ lock_ObtainWrite(&smb_rctLock);
+ }
+ }
+
+ if (nextp) {
+ if (nextp->refCount > 1) {
+ nextp->refCount--;
+ } else {
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_ReleaseFID(nextp);
+ lock_ObtainWrite(&smb_rctLock);
}
}
+
#ifdef DEBUG_SMB_REFCOUNT
if (fidp) {
afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
}
#endif
lock_ReleaseWrite(&smb_rctLock);
- return fidp;
+ return (fidp);
}
#ifdef DEBUG_SMB_REFCOUNT
}
-/* smb_ReleaseFID cannot be called while an cm_scache_t mutex lock is held */
-/* the sm_fid_t->mx and smb_rctLock must not be held */
+/* smb_ReleaseFID cannot be called while a cm_scache_t rwlock is held */
+/* the smb_fid_t->mx and smb_rctLock must not be held */
#ifdef DEBUG_SMB_REFCOUNT
void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
#else
if (ioctlp->ioctl.outAllocp)
free(ioctlp->ioctl.outAllocp);
free(ioctlp);
- }
+ }
+
+ smb_CleanupRPCFid(fidp);
+
lock_ReleaseMutex(&fidp->mx);
lock_FinalizeMutex(&fidp->mx);
free(fidp);
smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
normchar_t normName[MAX_PATH];
- cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0]));
+ if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0])) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
if(!cm_ClientStrCmpI(normName, vrock->shareName))
matchType = SMB_FINDSHARE_EXACT_MATCH;
else
matchType = SMB_FINDSHARE_PARTIAL_MATCH;
- if(vrock->match) free(vrock->match);
+ if(vrock->match)
+ free(vrock->match);
vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
vrock->matchType = matchType;
return 1;
}
- if (cm_ClientStrCmpIA(shareName, _C("IPC$")) == 0 ||
- cm_ClientStrCmpIA(shareName, _C("srvsvc")) == 0 ||
- cm_ClientStrCmpIA(shareName, _C("wkssvc")) == 0 ||
+ if (MSRPC_IsWellKnownService(shareName) ||
cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
) {
fschar_t ftemp[1024];
clientchar_t * p = shareName;
int rw = 0;
+ cm_scache_t * rscp;
+ cm_user_t *userp;
/* attempt to locate a partial match in root.afs. This is because
when using the ANSI RAP calls, the share name is limited to 13 chars
thyper.LowPart = 0;
vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
+ if (vrock.shareName == NULL)
+ return 0;
vrock.match = NULL;
vrock.matchType = 0;
- cm_HoldSCache(cm_data.rootSCachep);
- code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
- (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
- cm_ReleaseSCache(cm_data.rootSCachep);
+ userp = (uidp? (uidp->unp ? uidp->unp->userp : cm_rootUserp) : cm_rootUserp);
+ rscp = cm_RootSCachep(userp, &req);
+ cm_HoldSCache(rscp);
+ code = cm_ApplyDir(rscp, smb_FindShareProc, &vrock, &thyper,
+ userp, &req, NULL);
+ cm_ReleaseSCache(rscp);
free(vrock.shareName);
vrock.shareName = NULL;
}
/* Get the full name for this cell */
cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
- code = cm_SearchCellFile(cellname, ftemp, 0, 0);
-#ifdef AFS_AFSDB_ENV
+ code = cm_SearchCellRegistry(1, cellname, ftemp, 0, 0, 0);
+ if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellFile(cellname, ftemp, 0, 0);
if (code && cm_dnsEnabled) {
int ttl;
code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
}
-#endif
if (cellname)
free(cellname);
if (code == 0) {
clientchar_t temp[1024];
- cm_FsStringToClientString(ftemp, (int)cm_FsStrLen(ftemp), temp, 1024);
+ if (cm_FsStringToClientString(ftemp, -1, temp, 1024) != 0) {
cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
rw ? _C("/.%S/") : _C("/%S/"), temp);
*pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
return 1;
}
}
+ }
/* failure */
*pathNamep = NULL;
return 0;
HKEY hkCSCPolicy;
int retval = CSC_POLICY_MANUAL;
- RegCreateKeyEx( HKEY_LOCAL_MACHINE,
- AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
- 0,
- "AFS",
- REG_OPTION_NON_VOLATILE,
- KEY_READ,
- NULL,
- &hkCSCPolicy,
- NULL );
+ if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
+ 0,
+ "AFS",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ NULL,
+ &hkCSCPolicy,
+ NULL ) != ERROR_SUCCESS)
+ retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
len = sizeof(policy);
if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
len == 0) {
retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
}
+ else if (cm_ClientStrCmpIA(policy, _C("manual")) == 0)
+ {
+ retval = CSC_POLICY_MANUAL;
+ }
else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
{
retval = CSC_POLICY_DOCUMENTS;
if (!smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
}
- lock_ObtainMutex(&dsp->mx);
dsp->refCount++;
- lock_ReleaseMutex(&dsp->mx);
break;
}
}
void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
{
- lock_ObtainWrite(&smb_globalLock);
lock_ObtainMutex(&dsp->mx);
osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p",
dsp->cookie, dsp, dsp->scp);
lock_ReleaseWrite(&dsp->scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
- lock_ReleaseWrite(&smb_globalLock);
}
/* Must be called with the smb_globalLock held */
{
cm_scache_t *scp = NULL;
- lock_ObtainMutex(&dsp->mx);
osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
- if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
- if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
- smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
- osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
- lock_ReleaseMutex(&dsp->mx);
- lock_FinalizeMutex(&dsp->mx);
- scp = dsp->scp;
- osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
- dsp->cookie, dsp, scp);
- free(dsp);
- } else {
- lock_ReleaseMutex(&dsp->mx);
+ if (dsp->refCount == 0) {
+ lock_ObtainMutex(&dsp->mx);
+ if (dsp->flags & SMB_DIRSEARCH_DELETE) {
+ if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
+ smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
+ osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ lock_ReleaseMutex(&dsp->mx);
+ lock_FinalizeMutex(&dsp->mx);
+ scp = dsp->scp;
+ osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
+ dsp->cookie, dsp, scp);
+ free(dsp);
+ } else {
+ lock_ReleaseMutex(&dsp->mx);
+ }
}
/* do this now to avoid spurious locking hierarchy creation */
if (scp)
void smb_GCDirSearches(int isV3)
{
smb_dirSearch_t *prevp;
- smb_dirSearch_t *tp;
+ smb_dirSearch_t *dsp;
smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
int victimCount;
int i;
victimCount = 0; /* how many have we got so far */
- for (tp = smb_lastDirSearchp; tp; tp=prevp) {
+ for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
/* we'll move tp from queue, so
* do this early.
*/
- prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);
+ prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
/* if no one is using this guy, and we're either in the new protocol,
* or we're in the old one and this is a small enough ID to be useful
* to the old protocol, GC this guy.
*/
- if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
+ if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
/* hold and delete */
- lock_ObtainMutex(&tp->mx);
- tp->flags |= SMB_DIRSEARCH_DELETE;
- lock_ReleaseMutex(&tp->mx);
- victimsp[victimCount++] = tp;
- tp->refCount++;
+ lock_ObtainMutex(&dsp->mx);
+ dsp->flags |= SMB_DIRSEARCH_DELETE;
+ lock_ReleaseMutex(&dsp->mx);
+ victimsp[victimCount++] = dsp;
+ dsp->refCount++;
}
/* don't do more than this */
/* don't need to watch for refcount zero and deleted, since
* we haven't dropped the global lock.
*/
- lock_ObtainMutex(&dsp->mx);
dsp->refCount--;
- lock_ReleaseMutex(&dsp->mx);
++smb_dirSearchCounter;
continue;
}
dsp->cookie = smb_dirSearchCounter;
++smb_dirSearchCounter;
dsp->refCount = 1;
- lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
+ lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
dsp->lastTime = osi_Time();
osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
if (!smb_lastDirSearchp)
clientchar_t *inPathp)
{
clientchar_t *lastSlashp;
-
+ clientchar_t *streamp = NULL;
+ clientchar_t *typep = NULL;
+
lastSlashp = cm_ClientStrRChr(inPathp, '\\');
- if (lastComponentp)
+ if (lastComponentp) {
*lastComponentp = lastSlashp;
+ }
if (lastSlashp) {
+ /*
+ * If the name contains a stream name and a type
+ * and the stream name is the nul-string and the
+ * type is $DATA, then strip "::$DATA" from the
+ * last component string that is returned.
+ *
+ * Otherwise, return the full path name and allow
+ * the file name to be rejected because it contains
+ * a colon.
+ */
+ typep = cm_ClientStrRChr(lastSlashp, L':');
+ if (typep && cm_ClientStrCmpI(typep, L":$DATA") == 0) {
+ *typep = '\0';
+ streamp = cm_ClientStrRChr(lastSlashp, L':');
+ if (streamp && cm_ClientStrCmpI(streamp, L":") == 0) {
+ *streamp = '\0';
+ } else
+ *typep = ':';
+ osi_Log2(smb_logp, "smb_StripLastComponent found stream [%S] type [%S]",
+ osi_LogSaveClientString(smb_logp,streamp),
+ osi_LogSaveClientString(smb_logp,typep));
+ }
+
while (1) {
if (inPathp == lastSlashp)
break;
char **chainpp, int flags)
{
size_t cb;
+ afs_uint32 type = *inp++;
- if (*inp++ != 0x4)
- return NULL;
+ /*
+ * The first byte specifies the type of the input string.
+ * CIFS TR 1.0 3.2.10. This function only parses null terminated
+ * strings.
+ */
+ switch (type) {
+ /* Length Counted */
+ case 0x1: /* Data Block */
+ case 0x5: /* Variable Block */
+ cb = *inp++ << 16 | *inp++;
+ break;
+
+ /* Null-terminated string */
+ case 0x4: /* ASCII */
+ case 0x3: /* Pathname */
+ case 0x2: /* Dialect */
+ 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);
+ }
+ break;
+
+ default:
+ return NULL; /* invalid input */
+ }
#ifdef SMB_UNICODE
- if (!WANTS_UNICODE(pktp))
+ if (type == 0x2 /* Dialect */ || !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);
}
#endif
cb = sizeof(pktp->data);
}
- return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
+ flags | SMB_STRF_SRCNULTERM);
}
clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
*stringspp = spacep;
cchdest = lengthof(spacep->wdata);
- cm_Utf8ToUtf16(inp, (int)*pcb_max, spacep->wdata, cchdest);
+ cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
+ spacep->wdata, cchdest);
return spacep->wdata;
#ifdef SMB_UNICODE
if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
- if (!(flags & SMB_STRF_IGNORENULL))
+ if (!(flags & SMB_STRF_IGNORENUL))
*plen += sizeof(wchar_t);
return (unsigned char *) 1; /* return TRUE if we are using unicode */
cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
if (plen)
- *plen = ((flags & SMB_STRF_IGNORENULL)? cch_dest: cch_dest+1);
+ *plen = ((flags & SMB_STRF_IGNORENUL)? cch_dest: cch_dest+1);
return NULL;
}
return NULL;
*((wchar_t *) outp) = L'\0';
- if (plen && !(flags & SMB_STRF_IGNORENULL))
+ if (plen && !(flags & SMB_STRF_IGNORENUL))
*plen += sizeof(wchar_t);
return outp + sizeof(wchar_t);
}
}
if (plen)
- *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1: nchars);
+ *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENUL)? nchars - 1: nchars);
return outp + sizeof(wchar_t) * nchars;
}
cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
if (plen)
- *plen += ((flags & SMB_STRF_IGNORENULL)? cch_dest - 1: cch_dest);
+ *plen += ((flags & SMB_STRF_IGNORENUL)? cch_dest - 1: cch_dest);
return outp + cch_dest;
}
localNCB = 1;
}
- memset((char *)ncbp, 0, sizeof(NCB));
+ memset(ncbp, 0, sizeof(NCB));
extra = 2 * (*inp->wctp); /* space used by parms, in bytes */
tp = inp->wctp + 1+ extra; /* points to count of data bytes */
/* map CM_ERROR_* errors to NT 32-bit status codes */
/* NT Status codes are listed in ntstatus.h not winerror.h */
- if (code == CM_ERROR_NOSUCHCELL) {
- NTStatus = 0xC000000FL; /* No such file */
+ if (code == 0) {
+ NTStatus = 0;
+ }
+ else if (code == CM_ERROR_NOSUCHCELL) {
+ NTStatus = 0xC0000034L; /* Name not found */
}
else if (code == CM_ERROR_NOSUCHVOLUME) {
- NTStatus = 0xC000000FL; /* No such file */
+ NTStatus = 0xC0000034L; /* Name not found */
}
else if (code == CM_ERROR_TIMEDOUT) {
#ifdef COMMENT
NTStatus = 0xC00000CFL; /* Sharing Paused */
-#else
+
+ /* Do not send Timeout to the SMB redirector.
+ * It causes the redirector to drop the connection */
NTStatus = 0x00000102L; /* Timeout */
+ /* do not send Retry to the SMB redirector.
+ * It believes the error comes from the transport
+ * layer not from the SMB server. */
+ NTStatus = 0xC000022DL; /* Retry */
+#else
+ NTStatus = 0xC00000B5L; /* I/O Timeout */
#endif
}
else if (code == CM_ERROR_RETRY) {
+#ifdef COMMENT
NTStatus = 0xC000022DL; /* Retry */
+#else
+ NTStatus = 0xC00000B5L; /* I/O Timeout */
+#endif
}
else if (code == CM_ERROR_NOACCESS) {
NTStatus = 0xC0000022L; /* Access denied */
}
else if (code == CM_ERROR_NOSUCHFILE ||
code == CM_ERROR_BPLUS_NOMATCH) {
- NTStatus = 0xC000000FL; /* No such file */
+ NTStatus = 0xC0000034L; /* Name not found */
}
else if (code == CM_ERROR_NOSUCHPATH) {
NTStatus = 0xC000003AL; /* Object path not found */
else if (code == CM_ERROR_BADFDOP) {
NTStatus = 0xC0000022L; /* Access denied */
}
+ else if (code == CM_ERROR_UNKNOWN) {
+ NTStatus = 0xC0000022L; /* Access denied */
+ }
else if (code == CM_ERROR_EXISTS) {
NTStatus = 0xC0000035L; /* Object name collision */
}
#endif /* COMMENT */
}
else if (code == CM_ERROR_BADSHARENAME) {
- NTStatus = 0xC00000CCL; /* Bad network name */
+ NTStatus = 0xC00000BEL; /* Bad network path (server valid, share bad) */
}
else if (code == CM_ERROR_NOIPC) {
#ifdef COMMENT
NTStatus = 0xC000013DL; /* Remote Resources */
#endif
}
- else if (code == CM_ERROR_CLOCKSKEW) {
+ else if (code == CM_ERROR_CLOCKSKEW ||
+ code == RXKADNOAUTH) {
NTStatus = 0xC0000133L; /* Time difference at DC */
}
else if (code == CM_ERROR_BADTID) {
NTStatus = 0xC0000033L; /* Object name invalid */
}
else if (code == CM_ERROR_WOULDBLOCK) {
- NTStatus = 0xC0000055L; /* Lock not granted */
+ NTStatus = 0xC00000D8L; /* Can't wait */
}
else if (code == CM_ERROR_SHARING_VIOLATION) {
NTStatus = 0xC0000043L; /* Sharing violation */
else if (code == CM_ERROR_BUFFERTOOSMALL) {
NTStatus = 0xC0000023L; /* Buffer too small */
}
+ else if (code == CM_ERROR_BUFFER_OVERFLOW) {
+ NTStatus = 0x80000005L; /* Buffer overflow */
+ }
else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
NTStatus = 0xC0000035L; /* Object name collision */
}
NTStatus = 0xC0000257L; /* Path Not Covered */
}
else if (code == CM_ERROR_ALLBUSY) {
+#ifdef COMMENT
NTStatus = 0xC000022DL; /* Retry */
- }
+#else
+ NTStatus = 0xC0020018L; /* RPC_NT_SERVER_TOO_BUSY */
+#endif
+ }
else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
- NTStatus = 0xC00000BEL; /* Bad Network Path */
- }
- else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
- NTStatus = 0xC0000322L; /* No Kerberos key */
- }
+#ifdef COMMENT
+ NTStatus = 0xC000003AL; /* Path not found */
+#else
+ NTStatus = 0xC0020017L; /* RPC_NT_SERVER_UNAVAILABLE */
+#endif
+ }
+ 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_LOCK_NOT_GRANTED) {
NTStatus = 0xC0000055L; /* Lock Not Granted */
- } else {
+ }
+ else if (code == ENOMEM) {
+ NTStatus = 0xC0000017L; /* Out of Memory */
+ }
+ else if (code == CM_ERROR_RPC_MOREDATA) {
+ NTStatus = 0x80000005L; /* Buffer overflow */
+ }
+ else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
}
+/*
+ * NTSTATUS <-> Win32 Error Translation
+ * http://support.microsoft.com/kb/113996
+ */
+void smb_MapWin32Error(long code, unsigned long *Win32Ep)
+{
+ unsigned long Win32E;
+
+ /* map CM_ERROR_* errors to Win32 32-bit error codes */
+ if (code == 0) {
+ Win32E = 0;
+ }
+ else if (code == CM_ERROR_NOSUCHCELL) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_NOSUCHVOLUME) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_TIMEDOUT) {
+#ifdef COMMENT
+ Win32E = ERROR_SHARING_PAUSED; /* Sharing Paused */
+#else
+ Win32E = ERROR_UNEXP_NET_ERR; /* Timeout */
+#endif
+ }
+ else if (code == CM_ERROR_RETRY) {
+ Win32E = ERROR_RETRY; /* Retry */
+ }
+ else if (code == CM_ERROR_NOACCESS) {
+ Win32E = ERROR_ACCESS_DENIED; /* Access denied */
+ }
+ else if (code == CM_ERROR_READONLY) {
+ Win32E = ERROR_WRITE_PROTECT; /* Write protected */
+ }
+ else if (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_BPLUS_NOMATCH) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_NOSUCHPATH) {
+ Win32E = ERROR_PATH_NOT_FOUND; /* Object path not found */
+ }
+ else if (code == CM_ERROR_TOOBIG) {
+ Win32E = ERROR_BAD_EXE_FORMAT; /* Invalid image format */
+ }
+ else if (code == CM_ERROR_INVAL) {
+ Win32E = ERROR_INVALID_PARAMETER;/* Invalid parameter */
+ }
+ else if (code == CM_ERROR_BADFD) {
+ Win32E = ERROR_INVALID_HANDLE; /* Invalid handle */
+ }
+ else if (code == CM_ERROR_BADFDOP) {
+ Win32E = ERROR_ACCESS_DENIED; /* Access denied */
+ }
+ else if (code == CM_ERROR_UNKNOWN) {
+ Win32E = ERROR_ACCESS_DENIED; /* Access denied */
+ }
+ else if (code == CM_ERROR_EXISTS) {
+ Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+ }
+ else if (code == CM_ERROR_NOTEMPTY) {
+ Win32E = ERROR_DIR_NOT_EMPTY; /* Directory not empty */
+ }
+ else if (code == CM_ERROR_CROSSDEVLINK) {
+ Win32E = ERROR_NOT_SAME_DEVICE; /* Not same device */
+ }
+ else if (code == CM_ERROR_NOTDIR) {
+ Win32E = ERROR_DIRECTORY; /* Not a directory */
+ }
+ else if (code == CM_ERROR_ISDIR) {
+ Win32E = ERROR_ACCESS_DENIED; /* File is a directory */
+ }
+ else if (code == CM_ERROR_BADOP) {
+ Win32E = ERROR_NOT_SUPPORTED; /* Not supported */
+ }
+ else if (code == CM_ERROR_BADSHARENAME) {
+ Win32E = ERROR_BAD_NETPATH; /* Bad network path (server valid, share bad) */
+ }
+ else if (code == CM_ERROR_NOIPC) {
+#ifdef COMMENT
+ Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
+#else
+ Win32E = ERROR_REM_NOT_LIST; /* Remote Resources */
+#endif
+ }
+ else if (code == CM_ERROR_CLOCKSKEW ||
+ code == RXKADNOAUTH) {
+ Win32E = ERROR_TIME_SKEW; /* Time difference at DC */
+ }
+ else if (code == CM_ERROR_BADTID) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* SMB bad TID */
+ }
+ else if (code == CM_ERROR_USESTD) {
+ Win32E = ERROR_ACCESS_DENIED; /* SMB use standard */
+ }
+ else if (code == CM_ERROR_QUOTA) {
+ Win32E = ERROR_NOT_ENOUGH_QUOTA;/* Quota exceeded */
+ }
+ else if (code == CM_ERROR_SPACE) {
+ Win32E = ERROR_DISK_FULL; /* Disk full */
+ }
+ else if (code == CM_ERROR_ATSYS) {
+ Win32E = ERROR_INVALID_NAME; /* Object name invalid */
+ }
+ else if (code == CM_ERROR_BADNTFILENAME) {
+ Win32E = ERROR_INVALID_NAME; /* Object name invalid */
+ }
+ else if (code == CM_ERROR_WOULDBLOCK) {
+ Win32E = WAIT_TIMEOUT; /* Can't wait */
+ }
+ else if (code == CM_ERROR_SHARING_VIOLATION) {
+ Win32E = ERROR_SHARING_VIOLATION; /* Sharing violation */
+ }
+ else if (code == CM_ERROR_LOCK_CONFLICT) {
+ Win32E = ERROR_LOCK_VIOLATION; /* Lock conflict */
+ }
+ else if (code == CM_ERROR_PARTIALWRITE) {
+ Win32E = ERROR_DISK_FULL; /* Disk full */
+ }
+ else if (code == CM_ERROR_BUFFERTOOSMALL) {
+ Win32E = ERROR_INSUFFICIENT_BUFFER; /* Buffer too small */
+ }
+ else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+ Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+ }
+ else if (code == CM_ERROR_BADPASSWORD) {
+ Win32E = ERROR_LOGON_FAILURE; /* unknown username or bad password */
+ }
+ else if (code == CM_ERROR_BADLOGONTYPE) {
+ Win32E = ERROR_INVALID_LOGON_TYPE; /* logon type not granted */
+ }
+ else if (code == CM_ERROR_GSSCONTINUE) {
+ Win32E = ERROR_MORE_DATA; /* more processing required */
+ }
+ else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
+#ifdef COMMENT
+ Win32E = ERROR_CANT_RESOLVE_FILENAME; /* reparse point not resolved */
+#else
+ Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
+#endif
+ }
+ else if (code == CM_ERROR_PATH_NOT_COVERED) {
+ Win32E = ERROR_HOST_UNREACHABLE; /* Path Not Covered */
+ }
+ else if (code == CM_ERROR_ALLBUSY) {
+ Win32E = ERROR_RETRY; /* Retry */
+ }
+ else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+ Win32E = ERROR_HOST_UNREACHABLE; /* Path not found */
+ }
+ else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+ Win32E = SEC_E_NO_KERB_KEY; /* No Kerberos key */
+ }
+ else if (code == CM_ERROR_BAD_LEVEL) {
+ Win32E = ERROR_INVALID_LEVEL; /* Invalid Level */
+ }
+ else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+ Win32E = ERROR_NOT_LOCKED; /* Range Not Locked */
+ }
+ else if (code == CM_ERROR_NOSUCHDEVICE) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No Such Device */
+ }
+ else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+ Win32E = ERROR_LOCK_VIOLATION; /* Lock Not Granted */
+ }
+ else if (code == ENOMEM) {
+ Win32E = ERROR_NOT_ENOUGH_MEMORY; /* Out of Memory */
+ }
+ else if (code == CM_ERROR_RPC_MOREDATA) {
+ Win32E = ERROR_MORE_DATA; /* Buffer overflow */
+ }
+ else {
+ Win32E = ERROR_GEN_FAILURE; /* SMB non-specific error */
+ }
+
+ *Win32Ep = Win32E;
+ osi_Log2(smb_logp, "SMB SEND code %lX as Win32 %lX", code, Win32E);
+}
+
void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
unsigned char *classp)
{
fd, offset.HighPart, offset.LowPart, count);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreReadRaw Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
goto send1;
+ }
+ lock_ObtainMutex(&fidp->mx);
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFD;
+ }
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
code = CM_ERROR_NOSUCHFILE;
goto send1a;
}
-
pid = smbp->pid;
{
LARGE_INTEGER LOffset, LLength;
lock_ReleaseWrite(&fidp->scp->rw);
}
if (code) {
+ lock_ReleaseMutex(&fidp->mx);
goto send1a;
}
smb_RawBufs = *(char **)smb_RawBufs;
}
lock_ReleaseMutex(&smb_RawBufLock);
- if (!rawBuf)
+ if (!rawBuf) {
+ lock_ReleaseMutex(&fidp->mx);
goto send1a;
+ }
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL)
{
- lock_ReleaseMutex(&fidp->mx);
rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
if (rawBuf) {
/* Give back raw buffer */
send1:
ncbp = outp->ncbp;
- memset((char *)ncbp, 0, sizeof(NCB));
+ memset(ncbp, 0, sizeof(NCB));
ncbp->ncb_length = (unsigned short) finalCount;
ncbp->ncb_lsn = (unsigned char) vcp->lsn;
smb_SetSMBParmLong(outp, 9, caps);
time(&unixTime);
- smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+ cm_SearchTimeFromUnixTime(&dosTime, unixTime);
smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
smb_SetSMBParm(outp, 6, 1); /* next 2: session key */
smb_SetSMBParm(outp, 7, 1);
time(&unixTime);
- smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+ cm_SearchTimeFromUnixTime(&dosTime, unixTime);
smb_SetSMBParm(outp, 8, LOWORD(dosTime)); /* server time */
smb_SetSMBParm(outp, 9, HIWORD(dosTime)); /* server date */
osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
__FILE__, __LINE__);
+ /* on the first pass hold 'vcp' which was not held as 'nextp' */
+ if (vcp != nextp)
+ smb_HoldVCNoLock(vcp);
+
+ /*
+ * obtain a reference to 'nextp' now because we drop the
+ * smb_rctLock later and the list contents could change
+ * or 'vcp' could be destroyed when released.
+ */
nextp = vcp->nextp;
+ if (nextp)
+ smb_HoldVCNoLock(nextp);
- if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ smb_ReleaseVCNoLock(vcp);
continue;
+ }
- smb_HoldVCNoLock(vcp);
- if (nextp)
- smb_HoldVCNoLock(nextp);
smb_FormatResponsePacket(vcp, NULL, outp);
smbp = (smb_t *)outp;
outp->inCom = smbp->com = 0x2b /* Echo */;
lock_ObtainWrite(&smb_rctLock);
smb_ReleaseVCNoLock(vcp);
- if (nextp)
- smb_ReleaseVCNoLock(nextp);
}
lock_ReleaseWrite(&smb_rctLock);
smb_FreePacket(outp);
myTime.tm_sec = 0;
smb_localZero = mktime(&myTime);
-#ifndef USE_NUMERIC_TIME_CONV
- smb_CalculateNowTZ();
-#endif /* USE_NUMERIC_TIME_CONV */
#ifdef AFS_FREELANCE
if ( smb_localZero != old_localZero )
- cm_noteLocalMountPointChange();
+ cm_noteLocalMountPointChange(FALSE);
#endif
smb_CheckVCs();
if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
- wl->LLength, wl->key, NULL, &req);
+ wl->LLength, wl->key, 0, NULL, &req);
osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
char *tbp;
tbp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tbp, &tbp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
}
tp = cm_ClientStrRChr(pathp, '\\');
if (!tp)
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ if (!uidp)
+ return CM_ERROR_BADSMB;
userp = smb_GetUserFromUID(uidp);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
- if (uidp)
- smb_ReleaseUID(uidp);
+ smb_ReleaseUID(uidp);
if (!shareFound) {
smb_ReleaseTID(tidp, FALSE);
return CM_ERROR_BADSHARENAME;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp,
SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
- osi_assertx(pathp != NULL, "null path");
+ if (!pathp)
+ return CM_ERROR_BADSMB;
statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
osi_assertx(statBlockp != NULL, "null statBlock");
if (statLen == 0) {
}
static long
-smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
+smb_ApplyDirListPatches(cm_scache_t * dscp, smb_dirListPatch_t **dirPatchespp,
clientchar_t * tidPathp, clientchar_t * relPathp,
cm_user_t *userp, cm_req_t *reqp)
{
smb_dirListPatch_t *patchp;
smb_dirListPatch_t *npatchp;
clientchar_t path[AFSPATHMAX];
+ afs_uint32 rights;
+ afs_int32 mustFake = 0;
+
+ code = cm_FindACLCache(dscp, userp, &rights);
+ if (code == -1) {
+ lock_ObtainWrite(&dscp->rw);
+ code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&dscp->rw);
+ if (code == CM_ERROR_NOACCESS) {
+ mustFake = 1;
+ code = 0;
+ }
+ }
+ if (code)
+ goto cleanup;
+
+ if (!mustFake) { /* Bulk Stat */
+ afs_uint32 count;
+ cm_bulkStat_t *bsp = malloc(sizeof(cm_bulkStat_t));
+
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
+
+ for (patchp = *dirPatchespp, count=0;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ cm_scache_t *tscp = cm_FindSCache(&patchp->fid);
+ int i;
+
+ if (tscp) {
+ if (lock_TryWrite(&tscp->rw)) {
+ /* we have an entry that we can look at */
+ if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
+ /* we have a callback on it. Don't bother
+ * fetching this stat entry, since we're happy
+ * with the info we have.
+ */
+ lock_ReleaseWrite(&tscp->rw);
+ cm_ReleaseSCache(tscp);
+ continue;
+ }
+ lock_ReleaseWrite(&tscp->rw);
+ } /* got lock */
+ cm_ReleaseSCache(tscp);
+ } /* found entry */
+
+ i = bsp->counter++;
+ bsp->fids[i].Volume = patchp->fid.volume;
+ bsp->fids[i].Vnode = patchp->fid.vnode;
+ bsp->fids[i].Unique = patchp->fid.unique;
+
+ if (bsp->counter == AFSCBMAX) {
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
+ }
+ }
+
+ if (bsp->counter > 0)
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+
+ free(bsp);
+ }
for (patchp = *dirPatchespp; patchp; patchp =
(smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
continue;
}
lock_ObtainWrite(&scp->rw);
- code = cm_SyncOp(scp, NULL, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) {
+ if (mustFake || (scp->flags & CM_SCACHEFLAG_EACCESS) || !cm_HaveCallback(scp)) {
lock_ReleaseWrite(&scp->rw);
- cm_ReleaseSCache(scp);
- if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
- *dptr++ = SMB_ATTR_HIDDEN;
- continue;
- }
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ /* set the attribute */
+ switch (scp->fileType) {
+ case CM_SCACHETYPE_DIRECTORY:
+ case CM_SCACHETYPE_MOUNTPOINT:
+ case CM_SCACHETYPE_INVALID:
+ attr = SMB_ATTR_DIRECTORY;
+ break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ attr = SMB_ATTR_DIRECTORY;
+ else
+ attr = SMB_ATTR_NORMAL;
+ break;
+ default:
+ /* if we get here we either have a normal file
+ * or we have a file for which we have never
+ * received status info. In this case, we can
+ * check the even/odd value of the entry's vnode.
+ * odd means it is to be treated as a directory
+ * and even means it is to be treated as a file.
+ */
+ if (mustFake && (scp->fid.vnode & 0x1))
+ attr = SMB_ATTR_DIRECTORY;
+ else
+ attr = SMB_ATTR_NORMAL;
+ }
+ *dptr++ = attr;
+
+ /* 1969-12-31 23:59:58 +00*/
+ dosTime = 0xEBBFBF7D;
- 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)
- attr |= SMB_ATTR_HIDDEN;
- *dptr++ = attr;
+ /* copy out time */
+ shortTemp = (unsigned short) (dosTime & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out file length */
+ *((u_long *)dptr) = 0;
+ dptr += 4;
+ } else {
+ 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)
+ attr |= SMB_ATTR_HIDDEN;
+ *dptr++ = attr;
- /* get dos time */
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ /* get dos time */
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
- /* copy out time */
- shortTemp = (unsigned short) (dosTime & 0xffff);
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* and copy out date */
- shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* copy out time */
+ shortTemp = (unsigned short) (dosTime & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* copy out file length */
- *((u_long *)dptr) = scp->length.LowPart;
- dptr += 4;
- lock_ReleaseRead(&scp->rw);
+ /* copy out file length */
+ *((u_long *)dptr) = scp->length.LowPart;
+ dptr += 4;
+ lock_ReleaseRead(&scp->rw);
+ }
cm_ReleaseSCache(scp);
}
/* and mark the list as empty */
*dirPatchespp = NULL;
+ cleanup:
return code;
}
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp,
SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
- inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
- /* bail out if request looks bad */
- if (!tp || !pathp) {
+ inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+ if (!tp)
return CM_ERROR_BADSMB;
- }
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
memcpy(dsp->mask, mask, 12);
/* track if this is likely to match a lot of entries */
- if (smb_IsStarMask(mask))
+ if (smb_Is8Dot3StarMask(mask))
starPattern = 1;
else
starPattern = 0;
cm_ClientStrCpy(dsp->tidPath, lengthof(dsp->tidPath), tidPathp ? tidPathp : _C("/"));
cm_ClientStrCpy(dsp->relPath, lengthof(dsp->relPath), spacep->wdata);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
if (code == 0) {
#ifdef DFS_SUPPORT
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
*/
cm_HoldSCache(scp);
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;
- }
+ dsp->flags |= SMB_DIRSEARCH_BULKST;
lock_ReleaseWrite(&scp->rw);
}
}
code = 0;
returnedNames = 0;
while (1) {
- clientchar_t *actualName;
+ clientchar_t *actualName = NULL;
+ int free_actualName = 0;
clientchar_t shortName[13];
clientchar_t *shortNameEnd;
bufferp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, &req, &bufferp);
lock_ObtainMutex(&dsp->mx);
/* now, if we're doing a star match, do bulk fetching of all of
* the status info for files in the dir.
*/
- if (starPattern) {
- lock_ObtainWrite(&scp->rw);
- if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
- LargeIntegerGreaterThanOrEqualTo(thyper,
- scp->bulkStatProgress)) {
- code = cm_TryBulkStat(scp, &thyper, userp, &req);
- }
- lock_ReleaseWrite(&scp->rw);
- smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
- }
+ if (starPattern)
+ smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
+
lock_ObtainWrite(&scp->rw);
lock_ReleaseMutex(&dsp->mx);
if (code) {
/* Compute 8.3 name if necessary */
actualName = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
if (dep->fid.vnode != 0 && !cm_Is8Dot3(actualName)) {
- free(actualName);
+ if (actualName)
+ free(actualName);
cm_Gen8Dot3NameInt(dep->name, &dep->fid, shortName, &shortNameEnd);
actualName = shortName;
+ free_actualName = 0;
+ } else {
+ free_actualName = 1;
+ }
+
+ if (actualName == NULL) {
+ /* Couldn't convert the name for some reason */
+ osi_Log1(smb_logp, "SMB search dir skipping entry :[%s]",
+ osi_LogSaveString(smb_logp, dep->name));
+ goto nextEntry;
}
osi_Log3(smb_logp, "SMB search dir vn %d name %s (%S)",
} /* if we're including this name */
nextEntry:
+ if (free_actualName && actualName) {
+ free(actualName);
+ actualName = NULL;
+ }
+
/* and adjust curOffset to be where the new cookie is */
thyper.HighPart = 0;
thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
curOffset = LargeIntegerAdd(thyper, curOffset);
} /* while copying data for dir listing */
- /* If there is anything left to bulk stat ... */
- if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
- LargeIntegerGreaterThanOrEqualTo(thyper,
- scp->bulkStatProgress)) {
- thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
- code = cm_TryBulkStat(scp, &thyper, userp, &req);
- }
-
/* release the mutex */
lock_ReleaseWrite(&scp->rw);
if (bufferp) {
/* apply and free last set of patches; if not doing a star match, this
* will be empty, but better safe (and freeing everything) than sorry.
*/
- smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
+ smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
/* special return code for unsuccessful search */
if (code == 0 && dataLength < 21 && returnedNames == 0)
pdata = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, pdata, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive check path %S",
osi_LogSaveClientString(smb_logp, pathp));
- rootScp = cm_data.rootSCachep;
-
userp = smb_GetUserFromVCP(vcp, inp);
+ rootScp = cm_RootSCachep(userp, &req);
+
caseFold = CM_FLAG_CASEFOLD;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
dosTime, attribute);
- rootScp = cm_data.rootSCachep;
-
userp = smb_GetUserFromVCP(vcp, inp);
+ rootScp = cm_RootSCachep(userp, &req);
+
caseFold = CM_FLAG_CASEFOLD;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
smb_UnixTimeFromDosUTime(&attr.clientModTime, dosTime);
}
- if ((newScp->unixModeBits & 0222) && (attribute & SMB_ATTR_READONLY) != 0) {
+ if ((newScp->unixModeBits & 0200) && (attribute & SMB_ATTR_READONLY) != 0) {
/* we're told to make a writable file read-only */
attr.unixModeBits = newScp->unixModeBits & ~0222;
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
}
- else if ((newScp->unixModeBits & 0222) == 0 && (attribute & SMB_ATTR_READONLY) == 0) {
+ else if ((newScp->unixModeBits & 0200) == 0 && (attribute & SMB_ATTR_READONLY) == 0) {
/* we're told to make a read-only file writable */
attr.unixModeBits = newScp->unixModeBits | 0222;
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
osi_Log1(smb_logp, "SMB receive getfile attributes path %S",
osi_LogSaveClientString(smb_logp, pathp));
- rootScp = cm_data.rootSCachep;
-
userp = smb_GetUserFromVCP(vcp, inp);
+ rootScp = cm_RootSCachep(userp, &req);
+
/* we shouldn't need this for V3 requests, but we seem to */
caseFold = CM_FLAG_CASEFOLD;
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
} else
#endif /* DFS_SUPPORT */
if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-#ifdef undef
- /* use smb_Attributes instead. Also the fact that a file is
- * 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_INVALID)
- attrs = SMB_ATTR_DIRECTORY;
- else
- attrs = 0;
- if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
- attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
-#else
attrs = smb_Attributes(newScp);
-#endif
smb_SetSMBParm(outp, 0, attrs);
datap = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive open file [%S]", osi_LogSaveClientString(smb_logp, pathp));
attribute = smb_GetSMBParm(inp, 1);
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "CoreOpen rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreOpen rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
if (lastNamep && cm_ClientStrCmp(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathp, caseFold | CM_FLAG_FOLLOW, userp,
tidPathp, &req, &scp);
if (code) {
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assertx(fidp, "null smb_fid_t");
- /* save a pointer to the vnode */
- fidp->scp = scp;
- osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
- lock_ObtainWrite(&scp->rw);
- scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseWrite(&scp->rw);
-
- /* and the user */
- cm_HoldUser(userp);
- fidp->userp = userp;
-
lock_ObtainMutex(&fidp->mx);
if ((share & 0xf) == 0)
fidp->flags |= SMB_FID_OPENREAD_LISTDIR;
fidp->flags |= SMB_FID_OPENWRITE;
else
fidp->flags |= (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE);
- lock_ReleaseMutex(&fidp->mx);
- lock_ObtainRead(&scp->rw);
+ /* save the user */
+ cm_HoldUser(userp);
+ fidp->userp = userp;
+
+ /* and a pointer to the vnode */
+ fidp->scp = scp;
+ osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
+ lock_ObtainWrite(&scp->rw);
+ scp->flags |= CM_SCACHEFLAG_SMB_FID;
+
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(&fidp->mx);
lock_ReleaseRead(&scp->rw);
/* notify open */
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ /* Can't convert name */
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string.",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
match = cm_MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
cm_req_t req;
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
attribute = smb_GetSMBParm(inp, 0);
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive unlink %S",
osi_LogSaveClientString(smb_logp, pathp));
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold, userp, tidPathp,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold, userp, tidPathp,
&req, &dscp);
if (code) {
cm_ReleaseUser(userp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
rock.any = 0;
rock.maskp = cm_ClientStringToNormStringAlloc(smb_FindMask(pathp), -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
osi_Log1(smb_logp, "Unlinking %s",
osi_LogSaveString(smb_logp, entry->name));
+ /* We assume this works because entry->name was
+ successfully converted in smb_UnlinkProc() once. */
cm_FsStringToNormString(entry->name, -1,
normalizedName, lengthof(normalizedName));
cm_DirEntryListFree(&rock.matches);
+ done:
+ if (userp)
cm_ReleaseUser(userp);
+ if (dscp)
cm_ReleaseSCache(dscp);
+ if (rock.maskp)
free(rock.maskp);
if (code == 0 && !rock.any)
rockp = (smb_renameRock_t *) vrockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ /* Can't convert string */
+ osi_Log1(smb_logp, "Skpping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
}
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
+
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
userp, tidPathp, &req, &oldDscp);
if (code) {
cm_ReleaseUser(userp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
/* TODO: The old name could be a wildcard. The new name must not be */
- /* do the vnode call */
- rock.odscp = oldDscp;
- rock.ndscp = newDscp;
- rock.userp = userp;
- rock.reqp = &req;
- rock.vcp = vcp;
- rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
- rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
- rock.newNamep = newLastNamep;
- rock.fsOldName[0] = '\0';
- rock.clOldName[0] = '\0';
- rock.any = 0;
-
/* Check if the file already exists; if so return error */
code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) &&
osi_Log0(smb_logp, "Can't rename. Target already exists");
code = CM_ERROR_EXISTS;
}
+ goto done;
+ }
- if (tmpscp != NULL)
- cm_ReleaseSCache(tmpscp);
- cm_ReleaseSCache(newDscp);
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseUser(userp);
-
- free(rock.maskp);
- rock.maskp = NULL;
- return code;
+ /* do the vnode call */
+ rock.odscp = oldDscp;
+ rock.ndscp = newDscp;
+ rock.userp = userp;
+ rock.reqp = &req;
+ rock.vcp = vcp;
+ rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
}
+ rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+ rock.newNamep = newLastNamep;
+ rock.fsOldName[0] = '\0';
+ rock.clOldName[0] = '\0';
+ rock.any = 0;
/* Now search the directory for the pattern, and do the appropriate rename when found */
thyper.LowPart = 0; /* search dir from here */
/* if the call worked, stop doing the search now, since we
* really only want to rename one file.
*/
+ if (code)
+ osi_Log0(smb_logp, "cm_Rename failure");
osi_Log1(smb_logp, "cm_Rename returns %ld", code);
} else if (code == 0) {
code = CM_ERROR_NOSUCHFILE;
}
}
+ done:
if (tmpscp != NULL)
cm_ReleaseSCache(tmpscp);
- cm_ReleaseUser(userp);
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseSCache(newDscp);
-
- free(rock.maskp);
- rock.maskp = NULL;
+ if (userp)
+ cm_ReleaseUser(userp);
+ if (oldDscp)
+ cm_ReleaseSCache(oldDscp);
+ if (newDscp)
+ cm_ReleaseSCache(newDscp);
+ if (rock.maskp)
+ free(rock.maskp);
return code;
}
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
userp, tidPathp, &req, &oldDscp);
if (code) {
cm_ReleaseUser(userp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
cm_ReleaseSCache(oldDscp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
tp = smb_GetSMBData(inp, NULL);
oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!oldPathp)
+ return CM_ERROR_BADSMB;
newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!newPathp)
+ return CM_ERROR_BADSMB;
osi_Log2(smb_logp, "smb rename [%S] to [%S]",
osi_LogSaveClientString(smb_logp, oldPathp),
osi_LogSaveClientString(smb_logp, newPathp));
+ if (!cm_IsValidClientString(newPathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(newPathp, -1);
+ osi_Log1(smb_logp, "CoreRename rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreRename rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
code = smb_Rename(vcp,inp,oldPathp,newPathp,0);
osi_Log1(smb_logp, "smb rename returns 0x%x", code);
rockp = (smb_rmdirRock_t *) vrockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
else
cm_req_t req;
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
rock.any = 0;
rock.maskp = cm_ClientStringToNormStringAlloc(lastNamep, -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
clientchar_t clientName[MAX_PATH];
+ /* We assume this will succeed because smb_RmdirProc()
+ successfully converted entry->name once above. */
cm_FsStringToClientString(entry->name, -1, clientName, lengthof(clientName));
osi_Log1(smb_logp, "Removing directory %s",
}
}
+ done:
+ if (rock.matches)
cm_DirEntryListFree(&rock.matches);
+ if (userp)
cm_ReleaseUser(userp);
+ if (dscp)
cm_ReleaseSCache(dscp);
if (code == 0 && !rock.any)
code = CM_ERROR_NOSUCHFILE;
+ if (rock.maskp)
free(rock.maskp);
- rock.maskp = NULL;
return code;
}
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
- return CM_ERROR_BADFD;
-
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- return CM_ERROR_NOSUCHFILE;
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreFlush Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
+ return CM_ERROR_BADFD;
}
+ userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_IOCTL) {
- lock_ReleaseMutex(&fidp->mx);
- smb_ReleaseFID(fidp);
+ if (!fidp->scp || (fidp->flags & SMB_FID_IOCTL)) {
+ cm_ReleaseUser(userp);
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
return CM_ERROR_BADFD;
}
- lock_ReleaseMutex(&fidp->mx);
-
- userp = smb_GetUserFromVCP(vcp, inp);
- lock_ObtainMutex(&fidp->mx);
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
+ cm_ReleaseUser(userp);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
- cm_scache_t * scp = fidp->scp;
- cm_HoldSCache(scp);
- lock_ReleaseMutex(&fidp->mx);
- code = cm_FSync(scp, userp, &req);
- cm_ReleaseSCache(scp);
+ cm_scache_t * scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req, FALSE);
+ cm_ReleaseSCache(scp);
} else {
+ lock_ReleaseMutex(&fidp->mx);
code = 0;
- lock_ReleaseMutex(&fidp->mx);
}
- smb_ReleaseFID(fidp);
-
cm_ReleaseUser(userp);
-
+ smb_ReleaseFID(fidp);
return code;
}
vrockp = (struct smb_FullNameRock *)rockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
if (!cm_Is8Dot3(matchName)) {
clientchar_t shortName[13];
if (!userp) {
lock_ObtainMutex(&fidp->mx);
- if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
+ if (!fidp->userp && !(fidp->flags & (SMB_FID_IOCTL|
+ SMB_FID_RPC))) {
lock_ReleaseMutex(&fidp->mx);
osi_Log0(smb_logp, " No user specified. Not closing fid");
return CM_ERROR_BADFD;
lock_ObtainWrite(&smb_rctLock);
if (fidp->deleteOk) {
- osi_Log0(smb_logp, " Fid already closed.");
- lock_ReleaseWrite(&smb_rctLock);
- return CM_ERROR_BADFD;
+ osi_Log0(smb_logp, " Fid already closed.");
+ lock_ReleaseWrite(&smb_rctLock);
+ return CM_ERROR_BADFD;
}
fidp->deleteOk = 1;
lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
if (fidp->NTopen_dscp) {
- dscp = fidp->NTopen_dscp;
- cm_HoldSCache(dscp);
+ dscp = fidp->NTopen_dscp;
+ cm_HoldSCache(dscp);
}
- if (fidp->NTopen_pathp) {
- pathp = cm_ClientStrDup(fidp->NTopen_pathp);
- }
+ if (fidp->NTopen_pathp)
+ pathp = cm_ClientStrDup(fidp->NTopen_pathp);
if (fidp->scp) {
- scp = fidp->scp;
- cm_HoldSCache(scp);
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
}
/* Don't jump the gun on an async raw write */
(fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
== SMB_FID_OPENWRITE) {
if (dosTime != 0 && dosTime != -1) {
+ lock_ObtainWrite(&fidp->scp->rw);
scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
/* This fixes defect 10958 */
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
- smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
+ smb_UnixTimeFromDosUTime(&scp->clientModTime, dosTime);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
if (smb_AsyncStore != 2) {
lock_ReleaseMutex(&fidp->mx);
- code = cm_FSync(scp, userp, &req);
+ code = cm_FSync(scp, userp, &req, FALSE);
lock_ObtainMutex(&fidp->mx);
}
}
cm_key_t key;
long tcode;
- lock_ReleaseMutex(&fidp->mx);
+ lock_ReleaseMutex(&fidp->mx);
- /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
- in zero. */
+ /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
+ * in zero. */
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
lock_ObtainWrite(&scp->rw);
}
if (scp) {
- lock_ObtainWrite(&scp->rw);
+ lock_ObtainWrite(&scp->rw);
if (nullcreator && scp->creator == userp)
scp->creator = NULL;
- scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseWrite(&scp->rw);
- cm_ReleaseSCache(scp);
+ scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
}
if (pathp)
- free(pathp);
+ free(pathp);
return code;
}
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreClose Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
}
code = CM_ERROR_BADFDOP;
goto done2;
}
-
+
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFD;
+ goto done2;
+ }
+
smb_InitReq(&req);
bufferp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, &req, &bufferp);
lock_ObtainWrite(&scp->rw);
if (code) goto done;
osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
DWORD filter = 0;
cm_req_t req;
+ int needSyncOpDone = 0;
osi_Log3(smb_logp, "smb_WriteData fid %d, off 0x%x, size 0x%x",
fidp->fid, offsetp->LowPart, count);
/* now, copy the data one buffer at a time, until we've filled the
* request packet */
- while (1) {
- /* if we've copied all the data requested, we're done */
- if (count <= 0)
- break;
+ while (count != 0) {
/* handle over quota or out of space */
if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
+ if (needSyncOpDone) {
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ needSyncOpDone = 0;
+ }
lock_ReleaseMutex(&bufferp->mx);
buf_Release(bufferp);
bufferp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, &req, &bufferp);
lock_ObtainMutex(&bufferp->mx);
lock_ObtainWrite(&scp->rw);
bufferOffset = thyper;
/* now get the data in the cache */
- while (1) {
- code = cm_SyncOp(scp, bufferp, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK
- | CM_SCACHESYNC_WRITE
- | CM_SCACHESYNC_BUFLOCKED);
- if (code)
- goto done;
-
- cm_SyncOpDone(scp, bufferp,
- CM_SCACHESYNC_NEEDCALLBACK
- | CM_SCACHESYNC_WRITE
- | CM_SCACHESYNC_BUFLOCKED);
+ while (code == 0) {
+ if (!needSyncOpDone) {
+ code = cm_SyncOp(scp, bufferp, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ if (code)
+ goto done;
+
+ needSyncOpDone = 1;
+ }
/* If we're overwriting the entire buffer, or
* if we're writing at or past EOF, mark the
* Use minLength instead of scp->length, since
* the latter has already been updated by this
* call.
+ *
+ * The scp lock has been dropped multiple times
+ * so the minLength must be refreshed before it
+ * is used.
*/
+
+ minLength = scp->length;
+ if (LargeIntegerGreaterThan(minLength, scp->serverLength))
+ minLength = scp->serverLength;
+
if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength)
|| LargeIntegerEqualTo(offset, bufferp->offset)
&& (count >= cm_data.buf_blockSize
if (cm_HaveBuffer(scp, bufferp, 1)) break;
/* otherwise, load the buffer and try again */
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ needSyncOpDone = 0;
+
lock_ReleaseMutex(&bufferp->mx);
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&bufferp->mx);
lock_ObtainWrite(&scp->rw);
- if (code) break;
}
- if (code) {
- lock_ReleaseMutex(&bufferp->mx);
- buf_Release(bufferp);
- bufferp = NULL;
+ if (code)
goto done;
- }
} /* if (wrong buffer) ... */
/* now we have the right buffer loaded. Copy out the
op += nbytes;
count -= nbytes;
written += nbytes;
- thyper.LowPart = nbytes;
- thyper.HighPart = 0;
- offset = LargeIntegerAdd(thyper, offset);
- } /* while 1 */
+ offset = LargeIntegerAdd(offset, ConvertLongToLargeInteger(nbytes));
+ } /* while count != 0 */
done:
+ if (bufferp && needSyncOpDone) {
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ }
+
lock_ReleaseWrite(&scp->rw);
if (bufferp) {
lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
- && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
+ && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ {
+ lock_ReleaseMutex(&fidp->mx);
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
fidp->NTopen_dscp, fidp->NTopen_pathp,
NULL, TRUE);
- }
- lock_ReleaseMutex(&fidp->mx);
+ } else {
+ lock_ReleaseMutex(&fidp->mx);
+ }
if (code == 0) {
if (smb_AsyncStore > 0) {
smb_t* smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
+ cm_scache_t *scp;
cm_attr_t truncAttr; /* attribute struct used for truncating file */
char *op;
int inDataBlockCount;
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
- osi_Log0(smb_logp, "smb_ReceiveCoreWrite fid not found");
+ osi_Log2(smb_logp, "smb_ReceiveCoreWrite Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
}
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- return CM_ERROR_NOSUCHFILE;
- }
-
lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
osi_Log1(smb_logp, "smb_ReceiveCoreWrite ioctl code 0x%x", code);
return code;
}
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCWrite(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ osi_Log1(smb_logp, "smb_ReceiveCoreWrite RPC code 0x%x", code);
+ return code;
+ }
+
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFD;
+ }
+
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
userp = smb_GetUserFromVCP(vcp, inp);
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainWrite(&fidp->scp->rw);
- code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseWrite(&fidp->scp->rw);
+ lock_ObtainWrite(&scp->rw);
+ code = cm_LockCheckWrite(scp, LOffset, LLength, key);
+ lock_ReleaseWrite(&scp->rw);
if (code) {
osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
*/
lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+ lock_ObtainWrite(&fidp->scp->rw);
fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
fidp->scp->clientModTime = time(NULL);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
lock_ReleaseMutex(&fidp->mx);
done:
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
+ cm_ReleaseSCache(scp);
return code;
}
fd = smb_GetSMBParm(inp, 0);
fidp = smb_FindFID(vcp, fd, 0);
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_CloseFID(vcp, fidp, NULL, 0);
+ lock_ObtainMutex(&fidp->mx);
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return;
}
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+
osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
+ cm_scache_t *scp;
char *op;
unsigned short writeMode;
char *rawBuf;
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreWriteRaw Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
+ return CM_ERROR_BADFD;
+ }
+ lock_ObtainMutex(&fidp->mx);
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
return CM_ERROR_BADFD;
}
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+
{
unsigned pid;
cm_key_t key;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainWrite(&fidp->scp->rw);
- code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseWrite(&fidp->scp->rw);
+ lock_ObtainWrite(&scp->rw);
+ code = cm_LockCheckWrite(scp, LOffset, LLength, key);
+ lock_ReleaseWrite(&scp->rw);
if (code) {
+ cm_ReleaseSCache(scp);
smb_ReleaseFID(fidp);
return code;
}
*/
lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_LOOKSLIKECOPY) != SMB_FID_LOOKSLIKECOPY) {
+ lock_ObtainWrite(&fidp->scp->rw);
fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
fidp->scp->clientModTime = time(NULL);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
+ cm_ReleaseSCache(scp);
if (code) {
smb_SetSMBParm(outp, 0, total_written);
smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
+ cm_scache_t *scp;
char *op;
fd = smb_GetSMBParm(inp, 0);
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreRead Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- return CM_ERROR_NOSUCHFILE;
}
-
lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return code;
}
- lock_ReleaseMutex(&fidp->mx);
- {
- LARGE_INTEGER LOffset, LLength;
- cm_key_t key;
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCRead(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
- pid = smbp->pid;
- key = cm_GenerateKey(vcp->vcID, pid, fd);
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFD;
+ }
- LOffset.HighPart = 0;
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+
+ {
+ LARGE_INTEGER LOffset, LLength;
+ cm_key_t key;
+
+ pid = smbp->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+ LOffset.HighPart = 0;
LOffset.LowPart = offset.LowPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainWrite(&fidp->scp->rw);
- code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
- lock_ReleaseWrite(&fidp->scp->rw);
+ lock_ObtainWrite(&scp->rw);
+ code = cm_LockCheckRead(scp, LOffset, LLength, key);
+ lock_ReleaseWrite(&scp->rw);
}
if (code) {
+ cm_ReleaseSCache(scp);
smb_ReleaseFID(fidp);
return code;
}
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
+ cm_ReleaseSCache(scp);
return code;
}
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
-
- if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
- return CM_ERROR_EXISTS;
+ if (!pathp)
+ return CM_ERROR_BADSMB;
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
+ return CM_ERROR_EXISTS;
+
userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
userp, tidPathp, &req, &dscp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForDir(0, &setAttr);
+
code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
cm_scache_t *dscp; /* dir we're dealing with */
cm_scache_t *scp; /* file we're creating */
cm_attr_t setAttr;
- int initialModeBits;
smb_fid_t *fidp;
int attributes;
clientchar_t *lastNamep;
attributes = smb_GetSMBParm(inp, 0);
dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
- /* compute initial mode bits based on read-only flag in attributes */
- initialModeBits = 0666;
- if (attributes & SMB_ATTR_READONLY)
- initialModeBits &= ~0222;
-
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "CoreCreate rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreCreate rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
else {
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+ smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
/* try to find the file descriptor */
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveCoreSeek Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- return CM_ERROR_NOSUCHFILE;
}
-
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_IOCTL) {
+ if (!fidp->scp || (fidp->flags & SMB_FID_IOCTL)) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return CM_ERROR_BADFD;
}
+
+ if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
lock_ReleaseMutex(&fidp->mx);
-
+
userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
if (dp->procp) {
/* we have a recognized operation */
char * opName = myCrt_Dispatch(inp->inCom);
+ smb_t *smbp;
+
+ smbp = (smb_t *) inp;
- if (inp->inCom == 0x1d)
+ osi_Log5(smb_logp,"Dispatch %s mid 0x%x vcp 0x%p lana %d lsn %d",
+ opName, smbp->mid, vcp, vcp->lana, vcp->lsn);
+ 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",
- opName,vcp,vcp->lana,vcp->lsn);
+ } else {
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);
-#ifdef LOG_PACKET
- if ( code == CM_ERROR_BADSMB ||
- code == CM_ERROR_BADOP )
- smb_LogPacket(inp);
-#endif /* LOG_PACKET */
}
+ osi_Log5(smb_logp,"Dispatch return code 0x%x mid 0x%x vcp 0x%p lana %d lsn %d",
+ code, smbp->mid, vcp, vcp->lana, vcp->lsn);
newTime = GetTickCount();
- osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+ osi_Log3(smb_logp, "Dispatch %s mid 0x%x duration %d ms",
+ opName, smbp->mid, newTime - oldTime);
+
+#ifdef LOG_PACKET
+ if ( code == CM_ERROR_BADSMB ||
+ code == CM_ERROR_BADOP )
+ smb_LogPacket(inp);
+#endif /* LOG_PACKET */
+
+ /* ReceiveV3Tran2A handles its own logging */
+ if (inp->inCom != 0x32 && newTime - oldTime > 45000) {
+ smb_user_t *uidp;
+ smb_fid_t *fidp;
+ clientchar_t *treepath = NULL; /* do not free */
+ clientchar_t *pathname = NULL;
+ cm_fid_t afid = {0,0,0,0,0};
+
+ uidp = smb_FindUID(vcp, smbp->uid, 0);
+ smb_LookupTIDPath(vcp, smbp->tid, &treepath);
+ fidp = smb_FindFID(vcp, inp->fid, 0);
+
+ if (fidp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->NTopen_pathp)
+ pathname = fidp->NTopen_pathp;
+ if (fidp->scp)
+ afid = fidp->scp->fid;
+ } else {
+ if (inp->stringsp->wdata)
+ pathname = inp->stringsp->wdata;
+ }
+
+ afsi_log("Request %s duration %d ms user 0x%x \"%S\" pid 0x%x mid 0x%x tid 0x%x \"%S\" path? \"%S\" afid (%d.%d.%d.%d)",
+ opName, newTime - oldTime,
+ smbp->uid, uidp ? uidp->unp->name : NULL,
+ smbp->pid, smbp->mid, smbp->tid,
+ treepath,
+ pathname,
+ afid.cell, afid.volume, afid.vnode, afid.unique);
+
+ if (fidp)
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (uidp)
+ smb_ReleaseUID(uidp);
+ if (fidp)
+ smb_ReleaseFID(fidp);
+ }
if (oldGen != sessionGen) {
LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION,
}
}
+typedef struct _monitored_task {
+ osi_queue_t q;
+ INT_PTR task_id;
+ LARGE_INTEGER start_time;
+ BOOL started;
+ BOOL trace_timer_hit;
+ BOOL dump_timer_hit;
+} monitored_task;
+
+typedef struct osi_queueHT {
+ osi_queue_t * headp;
+ osi_queue_t * tailp;
+} osi_queueHT_t;
+
+static osi_queue_t *smb_monitored_tasks = NULL;
+static osi_queue_t *smb_free_monitored_tasks = NULL;
+
+static osi_mutex_t _monitor_mx;
+
+static HANDLE h_monitored_task_queue = NULL;
+static HANDLE h_monitored_task_shutdown = NULL;
+
+static time_t smb_last_dump_time = 0;
+
+DWORD smb_monitorReqs = 0;
+
+/* FILETIME comparison fuzz */
+#define MONITOR_FUZZ_TIMEOUT (1 * 10000000i64)
+
+/* Trace timeout is at 60 seconds */
+#define MONITOR_TRACE_TIMEOUT (60 * 10000000i64)
+
+/* Dump timeout is at 120 seconds */
+#define MONITOR_DUMP_TIMEOUT (120 * 10000000i64)
+
+/* Time before another dump is performed in seconds*/
+#define MONITOR_DUMP_RESET_TIMEOUT (600)
+
+static void smb_PurgeOldTaskMonitors(osi_queueHT_t * taskmq)
+{
+ FILETIME now;
+ LARGE_INTEGER earliest;
+ monitored_task * t;
+
+ GetSystemTimeAsFileTime(&now);
+ earliest.LowPart = now.dwLowDateTime;
+ earliest.HighPart = now.dwHighDateTime;
+ earliest.QuadPart -= MONITOR_FUZZ_TIMEOUT + MONITOR_DUMP_TIMEOUT;
+
+ while ((t = (monitored_task *) taskmq->headp) != NULL &&
+
+ (t->start_time.QuadPart < earliest.QuadPart ||
+
+ t->dump_timer_hit)) {
+
+ osi_QRemoveHT(&taskmq->headp,
+ &taskmq->tailp,
+ &t->q);
+
+ lock_ObtainMutex(&_monitor_mx);
+ osi_QAdd(&smb_free_monitored_tasks, &t->q);
+ lock_ReleaseMutex(&_monitor_mx);
+ }
+
+#ifdef INVARIANT_CHECK
+ {
+ LARGE_INTEGER last;
+
+ last.QuadPart = 0;
+
+ for (t = (monitored_task *) taskmq->headp;
+ t;
+ t = (monitored_task *) osi_QNext(&t->q)) {
+ osi_assert(last.QuadPart <= t->start_time.QuadPart);
+ last.QuadPart = t->start_time.QuadPart;
+ }
+ }
+#endif
+}
+
+static void smb_SlurpNewTaskMonitors(osi_queueHT_t * taskmq)
+{
+ monitored_task * task;
+ monitored_task * tasks;
+
+ lock_ObtainMutex(&_monitor_mx);
+ tasks = (monitored_task *) smb_monitored_tasks;
+ smb_monitored_tasks = NULL;
+ lock_ReleaseMutex(&_monitor_mx);
+
+ while (tasks) {
+
+ task = tasks;
+ osi_QRemove((osi_queue_t **) &tasks, &task->q);
+
+ if (task->started) {
+
+ osi_queue_t q;
+ osi_queue_t *p;
+
+ q.nextp = NULL;
+ q.prevp = taskmq->tailp;
+
+ /* Insertion sort by start_time. Earliest request is
+ first. Since we are likely to receive new requests
+ later, we start inserting from the back. */
+ for (p = &q;
+ osi_QPrev(p) &&
+ ((monitored_task *) osi_QPrev(p))->start_time.QuadPart > task->start_time.QuadPart;
+ p = osi_QPrev(p));
+
+ if (p == &q)
+ osi_QAddT(&taskmq->headp, &taskmq->tailp, &task->q);
+ else if (p->prevp == NULL)
+ osi_QAddH(&taskmq->headp, &taskmq->tailp, &task->q);
+ else {
+ osi_queue_t *o = p->prevp;
+
+ osi_assert(o->nextp == p);
+
+ task->q.nextp = p;
+ task->q.prevp = o;
+ p->prevp = &task->q;
+ o->nextp = &task->q;
+ }
+
+ } else {
+ /* Some task ending */
+
+ osi_queue_t * p;
+
+ for (p = taskmq->headp;
+ p != NULL;
+ p = osi_QNext(p)) {
+
+ monitored_task * mt = (monitored_task *) p;
+
+ if (mt->task_id == task->task_id) {
+
+ osi_QRemoveHT(&taskmq->headp,
+ &taskmq->tailp, p);
+
+ lock_ObtainMutex(&_monitor_mx);
+ osi_QAdd(&smb_free_monitored_tasks, p);
+ lock_ReleaseMutex(&_monitor_mx);
+
+ break;
+ }
+ }
+
+ lock_ObtainMutex(&_monitor_mx);
+ osi_QAdd(&smb_free_monitored_tasks, &task->q);
+ lock_ReleaseMutex(&_monitor_mx);
+ }
+ }
+
+#ifdef INVARIANT_CHECK
+ {
+ LARGE_INTEGER last;
+ monitored_task * t;
+
+ last.QuadPart = 0;
+
+ for (t = (monitored_task *) taskmq->headp;
+ t;
+ t = (monitored_task *) osi_QNext(&t->q)) {
+ osi_assert(last.QuadPart <= t->start_time.QuadPart);
+ last.QuadPart = t->start_time.QuadPart;
+ }
+ }
+#endif
+}
+
+static void smb_HandleTaskMonitorEvent(monitored_task * task)
+{
+ if (!task->trace_timer_hit) {
+
+ task->trace_timer_hit = TRUE;
+
+ osi_LogEnable(afsd_logp);
+ rx_DebugOnOff(TRUE);
+
+ } else if (!task->dump_timer_hit) {
+ time_t now;
+
+ time(&now);
+
+ if (smb_last_dump_time + MONITOR_DUMP_RESET_TIMEOUT < now) {
+ task->dump_timer_hit = TRUE;
+ smb_last_dump_time = now;
+
+ GenerateMiniDump(NULL);
+ }
+ }
+}
+
+/**
+ * Server request monitoring
+ *
+ * The server monitor runs in a separate thread and monitors server
+ * requests for potential timeouts. It examines notifcations queued
+ * by smb_NotifyRequestEvent() and waits for potential timeout events:
+ *
+ * - After MONITOR_TRACE_TIMEOUT threshold elapses, the monitor
+ * enables trace logging.
+ *
+ * - After MONITOR_DUMP_TIMEOUT threshold elapses, the monitor writes
+ * out a dump file that will hopefully contain enough evidence to
+ * figure out why the timeout event occurred.
+ *
+ */
+void smb_ServerMonitor(VOID * parmp)
+{
+ osi_queueHT_t in_progress = { NULL, NULL };
+ HANDLE h_timer = NULL;
+
+ HANDLE h_all[3];
+
+ h_monitored_task_queue = CreateEvent(NULL, FALSE, FALSE, "Local\\OpenAFSTaskMonitor");
+ h_monitored_task_shutdown = CreateEvent(NULL, FALSE, FALSE, "Local\\OpenAFSTaskMonitorShutdown");
+ h_timer = CreateWaitableTimer(NULL, FALSE, "Local\\OpenAFSTaskMonitorTimer");
+
+ lock_InitializeMutex(&_monitor_mx, "Request monitor lock", LOCK_HIERARCHY_SMB_MONITOR);
+
+ h_all[0] = h_monitored_task_queue;
+ h_all[1] = h_timer;
+ h_all[2] = h_monitored_task_shutdown;
+
+ while(1) {
+ DWORD rv;
+
+ rv = WaitForMultipleObjects(3, h_all, FALSE, INFINITE);
+
+ if (rv == WAIT_OBJECT_0) {
+
+ smb_SlurpNewTaskMonitors(&in_progress);
+
+ } else if (rv == WAIT_OBJECT_0 + 1) {
+
+ smb_HandleTaskMonitorEvent((monitored_task *) in_progress.headp);
+
+ } else {
+
+ break;
+
+ }
+
+ /* refresh timers */
+ {
+ monitored_task * t;
+
+ smb_PurgeOldTaskMonitors(&in_progress);
+ t = (monitored_task *) in_progress.headp;
+
+ if (t && !t->trace_timer_hit) {
+ LARGE_INTEGER due;
+
+ due = t->start_time;
+ due.QuadPart += MONITOR_TRACE_TIMEOUT;
+
+ SetWaitableTimer(h_timer, &due, 0, NULL, NULL, FALSE);
+ } else if (t && !t->dump_timer_hit) {
+
+ LARGE_INTEGER due;
+
+ due = t->start_time;
+ due.QuadPart += MONITOR_DUMP_TIMEOUT;
+
+ SetWaitableTimer(h_timer, &due, 0, NULL, NULL, FALSE);
+ } else {
+ CancelWaitableTimer(h_timer);
+
+ /* CancelWaitableTimer() doesn't reset the timer if it
+ was already signalled. */
+ WaitForSingleObject(h_timer, 0);
+ }
+ }
+ }
+
+ {
+ HANDLE h;
+
+ h = h_monitored_task_queue;
+ h_monitored_task_queue = NULL;
+ CloseHandle(h);
+
+ h = h_monitored_task_shutdown;
+ h_monitored_task_shutdown = NULL;
+ CloseHandle(h);
+
+ CloseHandle(h_timer);
+
+ lock_FinalizeMutex(&_monitor_mx);
+ }
+
+ {
+ monitored_task * task;
+
+ while (in_progress.headp) {
+ task = (monitored_task *) in_progress.headp;
+ osi_QRemoveHT(&in_progress.headp, &in_progress.tailp, &task->q);
+ free(task);
+ }
+
+ for (task = (monitored_task *) smb_free_monitored_tasks;
+ task; task = (monitored_task *) smb_free_monitored_tasks) {
+ osi_QRemove(&smb_free_monitored_tasks, &task->q);
+ free(task);
+ }
+
+ for (task = (monitored_task *) smb_monitored_tasks;
+ task; task = (monitored_task *) smb_monitored_tasks) {
+ osi_QRemove(&smb_monitored_tasks, &task->q);
+ free(task);
+ }
+ }
+}
+
+void smb_NotifyRequestEvent(INT_PTR task_id, BOOL started)
+{
+ monitored_task * task;
+
+ lock_ObtainMutex(&_monitor_mx);
+ task = (monitored_task *) smb_free_monitored_tasks;
+ if (task)
+ osi_QRemove(&smb_free_monitored_tasks, &task->q);
+ lock_ReleaseMutex(&_monitor_mx);
+
+ if (task == NULL)
+ task = malloc(sizeof(monitored_task));
+ memset(task, 0, sizeof(*task));
+
+ task->task_id = task_id;
+ task->started = started;
+
+ {
+ FILETIME now;
+
+ GetSystemTimeAsFileTime(&now);
+ task->start_time.HighPart = now.dwHighDateTime;
+ task->start_time.LowPart = now.dwLowDateTime;
+ }
+
+ lock_ObtainMutex(&_monitor_mx);
+ osi_QAdd(&smb_monitored_tasks, &task->q);
+ lock_ReleaseMutex(&_monitor_mx);
+
+ SetEvent(h_monitored_task_queue);
+}
+
+void smb_ShutdownMonitor()
+{
+ SetEvent(h_monitored_task_shutdown);
+}
+
/*
* The top level loop for handling SMB request messages. Each server thread
* has its own NCB and buffer for sending replies (outncbp, outbufp), but the
vcp = NULL;
}
- smb_ResetServerPriority();
+ cm_ResetServerPriority();
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
FALSE, INFINITE);
continue;
}
- smb_SetRequestStartTime();
+ cm_SetRequestStartTime();
+ if (smb_monitorReqs) {
+ smb_NotifyRequestEvent(GetCurrentThreadId(), TRUE);
+ }
vcp->errorCount = 0;
bufp = (struct smb_packet *) ncbp->ncb_buffer;
if (smbp->com == 0x1d) {
/* Special handling for Write Raw */
raw_write_cont_t rwc;
- EVENT_HANDLE rwevent;
- char eventName[MAX_PATH];
smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
if (rwc.code == 0) {
- rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, TEXT("smb_Server() rwevent"));
+ EVENT_HANDLE rwevent;
+ char eventName[MAX_PATH];
+
+ snprintf(eventName, MAX_PATH, "smb_Server() rwevent %d", myIdx);
+ rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
+
ncbp->ncb_command = NCBRECV | ASYNCH;
ncbp->ncb_lsn = (unsigned char) vcp->lsn;
ncbp->ncb_lana_num = vcp->lana;
}
#endif
+ if (smb_monitorReqs) {
+ smb_NotifyRequestEvent(GetCurrentThreadId(), FALSE);
+ }
smb_concurrentCalls--;
doneWithNCB:
int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
INT_PTR lana = (INT_PTR) parmp;
char eventName[MAX_PATH];
+ int bridgeCount = 0;
+ int nowildCount = 0;
sprintf(eventName,"smb_Listener_lana_%d", (unsigned char)lana);
ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if (code == NRC_NAMERR) {
/* An smb shutdown or Vista resume must have taken place */
- osi_Log2(smb_logp,
+ osi_Log1(smb_logp,
"NCBLISTEN lana=%d failed with NRC_NAMERR.",
- ncbp->ncb_lana_num, code);
+ ncbp->ncb_lana_num);
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NAMERR.", ncbp->ncb_lana_num);
if (lock_TryMutex(&smb_StartedLock)) {
lana_list.lana[i] = LANA_INVALID;
} else if (code == NRC_BRIDGE || code != 0) {
int lanaRemaining = 0;
+ if (code == NRC_BRIDGE) {
+ if (++bridgeCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_BRIDGE, retrying ...", ncbp->ncb_lana_num);
+ continue;
+ }
+ } else if (code == NRC_NOWILD) {
+ if (++nowildCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NOWILD, retrying ...", ncbp->ncb_lana_num);
+
+ if (bridgeCount > 0) {
+ memset(ncbp, 0, sizeof(*ncbp));
+ ncbp->ncb_command = NCBADDNAME;
+ ncbp->ncb_lana_num = (UCHAR)lana;
+ /* pad out with spaces instead of null termination */
+ len = (long)strlen(smb_localNamep);
+ strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
+ for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+ code = Netbios(ncbp);
+ }
+ continue;
+ }
+ }
+
while (!lock_TryMutex(&smb_StartedLock)) {
if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
goto exit_thread;
osi_Log2(smb_logp,
"NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
ncbp->ncb_lana_num, ncb_error_string(code));
+ afsi_log("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] == lana) {
}
#endif /* 0 */
+ /* a successful packet received. clear bridge error count */
+ bridgeCount = 0;
+ nowildCount = 0;
+
/* check for remote conns */
/* first get remote name and insert null terminator */
memcpy(rname, ncbp->ncb_callname, NCBNAMSZ);
}
static void
+configureBackConnectionHostNames(void)
+{
+ /* On Windows XP SP2, Windows 2003 SP1, and all future Windows operating systems
+ * there is a restriction on the use of SMB authentication on loopback connections.
+ * There are two work arounds available:
+ *
+ * (1) We can disable the check for matching host names. This does not
+ * require a reboot:
+ * [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
+ * "DisableLoopbackCheck"=dword:00000001
+ *
+ * (2) We can add the AFS SMB/CIFS service name to an approved list. This
+ * does require a reboot:
+ * [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0]
+ * "BackConnectionHostNames"=multi-sz
+ *
+ * The algorithm will be:
+ * (1) Check to see if cm_NetbiosName exists in the BackConnectionHostNames list
+ * (2a) If not, add it to the list. (This will not take effect until the next reboot.)
+ * (2b1) and check to see if DisableLoopbackCheck is set.
+ * (2b2) If not set, set the DisableLoopbackCheck value to 0x1
+ * (2b3) and create HKLM\SOFTWARE\OpenAFS\Client UnsetDisableLoopbackCheck
+ * (2c) else If cm_NetbiosName exists in the BackConnectionHostNames list,
+ * check for the UnsetDisableLoopbackCheck value.
+ * If set, set the DisableLoopbackCheck flag to 0x0
+ * and delete the UnsetDisableLoopbackCheck value
+ *
+ * Starting in Longhorn Beta 1, an entry in the BackConnectionHostNames value will
+ * force Windows to use the loopback authentication mechanism for the specified
+ * services.
+ *
+ * Do not permit the "DisableLoopbackCheck" value to be removed within the same
+ * service session that set it.
+ */
+ HKEY hkLsa;
+ HKEY hkMSV10;
+ HKEY hkClient;
+ DWORD dwType;
+ DWORD dwSize, dwAllocSize;
+ DWORD dwValue;
+ PBYTE pHostNames = NULL, pName = NULL;
+ BOOL bNameFound = FALSE;
+ static BOOL bLoopbackCheckDisabled = FALSE;
+
+ /* BackConnectionHostNames and DisableLoopbackCheck */
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0",
+ 0,
+ KEY_READ|KEY_WRITE,
+ &hkMSV10) == ERROR_SUCCESS )
+ {
+ if ((RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0,
+ &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+ (dwType == REG_MULTI_SZ))
+ {
+ dwAllocSize += 1 /* in case the source string is not nul terminated */
+ + (DWORD)strlen(cm_NetbiosName) + 2;
+ pHostNames = malloc(dwAllocSize);
+ dwSize = dwAllocSize;
+ if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType,
+ pHostNames, &dwSize) == ERROR_SUCCESS)
+ {
+ for (pName = pHostNames;
+ (pName - pHostNames < (int) dwSize) && *pName ;
+ pName += strlen(pName) + 1)
+ {
+ if ( !stricmp(pName, cm_NetbiosName) ) {
+ bNameFound = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !bNameFound ) {
+ size_t size = strlen(cm_NetbiosName) + 2;
+ if ( !pHostNames ) {
+ pHostNames = malloc(size);
+ pName = pHostNames;
+ }
+ StringCbCopyA(pName, size, cm_NetbiosName);
+ pName += size - 1;
+ *pName = '\0'; /* add a second nul terminator */
+
+ dwType = REG_MULTI_SZ;
+ dwSize = (DWORD)(pName - pHostNames + 1);
+ RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize);
+
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+ 0,
+ KEY_READ|KEY_WRITE,
+ &hkLsa) == ERROR_SUCCESS )
+ {
+ dwSize = sizeof(DWORD);
+ if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS ||
+ dwValue == 0 ) {
+ dwType = REG_DWORD;
+ dwSize = sizeof(DWORD);
+ dwValue = 1;
+ RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
+
+ if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_OPENAFS_SUBKEY,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ|KEY_WRITE,
+ NULL,
+ &hkClient,
+ NULL) == ERROR_SUCCESS) {
+
+ dwType = REG_DWORD;
+ dwSize = sizeof(DWORD);
+ dwValue = 1;
+ RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
+ bLoopbackCheckDisabled = TRUE;
+ RegCloseKey(hkClient);
+ }
+ RegCloseKey(hkLsa);
+ }
+ }
+ } else if (!bLoopbackCheckDisabled) {
+ if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_OPENAFS_SUBKEY,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ|KEY_WRITE,
+ NULL,
+ &hkClient,
+ NULL) == ERROR_SUCCESS) {
+
+ dwSize = sizeof(DWORD);
+ if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS &&
+ dwValue == 1 ) {
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+ 0,
+ KEY_READ|KEY_WRITE,
+ &hkLsa) == ERROR_SUCCESS )
+ {
+ RegDeleteValue(hkLsa, "DisableLoopbackCheck");
+ RegCloseKey(hkLsa);
+ }
+ }
+ RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck");
+ RegCloseKey(hkClient);
+ }
+ }
+
+ if (pHostNames) {
+ free(pHostNames);
+ pHostNames = NULL;
+ }
+
+ RegCloseKey(hkMSV10);
+ }
+}
+
+
+static void
+configureExtendedSMBSessionTimeouts(void)
+{
+ /*
+ * In a Hot Fix to Windows 2003 SP2, the smb redirector was given the following
+ * new functionality:
+ *
+ * [HKLM\SYSTEM\CurrentControlSet\Services\LanManWorkstation\Parameters]
+ * "ReconnectableServers" REG_MULTI_SZ
+ * "ExtendedSessTimeout" REG_DWORD (seconds)
+ * "ServersWithExtendedSessTimeout" REG_MULTI_SZ
+ *
+ * These values can be used to prevent the smb redirector from timing out
+ * smb connection to the afs smb server prematurely.
+ */
+ HKEY hkLanMan;
+ DWORD dwType;
+ DWORD dwSize, dwAllocSize;
+ DWORD dwValue;
+ PBYTE pHostNames = NULL, pName = NULL;
+ BOOL bNameFound = FALSE;
+
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters",
+ 0,
+ KEY_READ|KEY_WRITE,
+ &hkLanMan) == ERROR_SUCCESS )
+ {
+ if ((RegQueryValueEx( hkLanMan, "ReconnectableServers", 0,
+ &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+ (dwType == REG_MULTI_SZ))
+ {
+ dwAllocSize += 1 /* in case the source string is not nul terminated */
+ + (DWORD)strlen(cm_NetbiosName) + 2;
+ pHostNames = malloc(dwAllocSize);
+ dwSize = dwAllocSize;
+ if (RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, &dwType,
+ pHostNames, &dwSize) == ERROR_SUCCESS)
+ {
+ for (pName = pHostNames;
+ (pName - pHostNames < (int) dwSize) && *pName ;
+ pName += strlen(pName) + 1)
+ {
+ if ( !stricmp(pName, cm_NetbiosName) ) {
+ bNameFound = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !bNameFound ) {
+ size_t size = strlen(cm_NetbiosName) + 2;
+ if ( !pHostNames ) {
+ pHostNames = malloc(size);
+ pName = pHostNames;
+ }
+ StringCbCopyA(pName, size, cm_NetbiosName);
+ pName += size - 1;
+ *pName = '\0'; /* add a second nul terminator */
+
+ dwType = REG_MULTI_SZ;
+ dwSize = (DWORD)(pName - pHostNames + 1);
+ RegSetValueEx( hkLanMan, "ReconnectableServers", 0, dwType, pHostNames, dwSize);
+ }
+
+ if (pHostNames) {
+ free(pHostNames);
+ pHostNames = NULL;
+ }
+
+ if ((RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0,
+ &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+ (dwType == REG_MULTI_SZ))
+ {
+ dwAllocSize += 1 /* in case the source string is not nul terminated */
+ + (DWORD)strlen(cm_NetbiosName) + 2;
+ pHostNames = malloc(dwAllocSize);
+ dwSize = dwAllocSize;
+ if (RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, &dwType,
+ pHostNames, &dwSize) == ERROR_SUCCESS)
+ {
+ for (pName = pHostNames;
+ (pName - pHostNames < (int) dwSize) && *pName ;
+ pName += strlen(pName) + 1)
+ {
+ if ( !stricmp(pName, cm_NetbiosName) ) {
+ bNameFound = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !bNameFound ) {
+ size_t size = strlen(cm_NetbiosName) + 2;
+ if ( !pHostNames ) {
+ pHostNames = malloc(size);
+ pName = pHostNames;
+ }
+ StringCbCopyA(pName, size, cm_NetbiosName);
+ pName += size - 1;
+ *pName = '\0'; /* add a second nul terminator */
+
+ dwType = REG_MULTI_SZ;
+ dwSize = (DWORD)(pName - pHostNames + 1);
+ RegSetValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, dwType, pHostNames, dwSize);
+ }
+
+ if (pHostNames) {
+ free(pHostNames);
+ pHostNames = NULL;
+ }
+
+ if ((RegQueryValueEx( hkLanMan, "ExtendedSessTimeout", 0,
+ &dwType, (LPBYTE)&dwValue, &dwAllocSize) != ERROR_SUCCESS) ||
+ (dwType != REG_DWORD))
+ {
+ dwType = REG_DWORD;
+ dwSize = sizeof(dwValue);
+ dwValue = 300; /* 5 minutes */
+ RegSetValueEx( hkLanMan, "ExtendedSessTimeout", 0, dwType, (const BYTE *)&dwValue, dwSize);
+ }
+ RegCloseKey(hkLanMan);
+ }
+}
+
+static void
smb_LanAdapterChangeThread(void *param)
{
/*
SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway,
LANA_NETBIOS_NAME_FULL)) &&
lanaNum != LANA_INVALID && smb_LANadapter != lanaNum) {
- if ( isGateway != bGateway ||
- strcmp(cm_NetbiosName, NetbiosName) ) {
+ if ( isGateway != bGateway ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): gateway %d != %d",
+ smb_LANadapter, lanaNum, isGateway, bGateway);
+ change = 1;
+ } else if (strcmp(cm_NetbiosName, NetbiosName) ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): name %s != %s",
+ smb_LANadapter, lanaNum, cm_NetbiosName, NetbiosName);
change = 1;
} else {
NCB *ncbp = smb_GetNCB();
ncbp->ncb_length = sizeof(temp_list);
code = Netbios(ncbp);
if (code == 0) {
- if (temp_list.length != lana_list.length)
+ if (temp_list.length != lana_list.length) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lan list length changed %d != %d",
+ smb_LANadapter, lanaNum, temp_list.length, lana_list.length);
change = 1;
- else {
+ } else {
for (i=0; i<lana_list.length; i++) {
if ( temp_list.lana[i] != lana_list.lana[i] ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lana[%d] %d != %d",
+ smb_LANadapter, lanaNum, i, temp_list.lana[i], lana_list.lana[i]);
change = 1;
break;
}
}
if (change) {
- afsi_log("Lan Adapter Change detected");
smb_StopListeners(1);
smb_RestartListeners(1);
}
}
afsi_log("smb_StartListeners");
+ /* Ensure the AFS Netbios Name is registered to allow loopback access */
+ configureBackConnectionHostNames();
+
+ /* Configure Extended SMB Session Timeouts */
+ if (msftSMBRedirectorSupportsExtendedTimeouts()) {
+ afsi_log("Microsoft SMB Redirector supports Extended Timeouts");
+ configureExtendedSMBSessionTimeouts();
+ }
+
smb_ListenerState = SMB_LISTENER_STARTED;
cm_VolStatus_Network_Started(cm_NetbiosName
#ifdef _WIN64
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
code = Netbios(ncbp);
- afsi_log("Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
+ afsi_log("StopListener: Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
/* and then reset the LANA; this will cause the listener threads to exit */
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- afsi_log("Netbios NCBRESET lana %d error code %d", lana, code);
+ afsi_log("StopListener: Netbios NCBRESET lana %d error code %d", lana, code);
} else {
- afsi_log("Netbios NCBRESET lana %d succeeded", lana);
+ afsi_log("StopListener: Netbios NCBRESET lana %d succeeded", lana);
}
if (wait)
{
thread_t phandle;
int lpid;
- INT_PTR i;
+ UINT_PTR i;
struct tm myTime;
EVENT_HANDLE retHandle;
char eventName[MAX_PATH];
int startListeners = 0;
- smb_TlsRequestSlot = TlsAlloc();
-
smb_MBfunc = aMBfunc;
smb_useV3 = useV3;
myTime.tm_sec = 0;
smb_localZero = mktime(&myTime);
-#ifndef USE_NUMERIC_TIME_CONV
- /* Initialize kludge-GMT */
- smb_CalculateNowTZ();
-#endif /* USE_NUMERIC_TIME_CONV */
#ifdef AFS_FREELANCE_CLIENT
/* Make sure the root.afs volume has the correct time */
- cm_noteLocalMountPointChange();
+ cm_noteLocalMountPointChange(FALSE);
#endif
/* initialize the remote debugging log */
smb_logp = logp;
/* and the global lock */
- lock_InitializeRWLock(&smb_globalLock, "smb global lock");
- lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
+ lock_InitializeRWLock(&smb_globalLock, "smb global lock", LOCK_HIERARCHY_SMB_GLOBAL);
+ lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock", LOCK_HIERARCHY_SMB_RCT_GLOBAL);
/* Raw I/O data structures */
- lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
+ lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock", LOCK_HIERARCHY_SMB_RAWBUF);
- lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
- lock_InitializeMutex(&smb_StartedLock, "smb started lock");
+ lock_InitializeMutex(&smb_ListenerLock, "smb listener lock", LOCK_HIERARCHY_SMB_LISTENER);
+ lock_InitializeMutex(&smb_StartedLock, "smb started lock", LOCK_HIERARCHY_SMB_STARTED);
/* 4 Raw I/O buffers */
smb_RawBufs = calloc(65536,1);
);
if (nts != STATUS_SUCCESS && ntsEx != STATUS_SUCCESS) {
- char message[AFSPATHMAX];
- sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
- nts, ntsEx);
- OutputDebugString(message);
- afsi_log(message);
+ osi_Log2(smb_logp, "MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
+ nts, ntsEx);
+
+ afsi_log("MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x", nts, ntsEx);
} else {
- OutputDebugString("MsV1_0SetProcessOption success");
+ osi_Log0(smb_logp, "MsV1_0SetProcessOption success");
afsi_log("MsV1_0SetProcessOption success");
}
/* END - code from Larry */
osi_assertx(phandle != NULL, "smb_WaitingLocksDaemon thread creation failure");
thrd_CloseHandle(phandle);
+ if (smb_monitorReqs) {
+ phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerMonitor,
+ NULL, 0, &lpid, "smb_ServerMonitor");
+ osi_assertx(phandle != NULL, "smb_ServerMonitor thread creation failure");
+ thrd_CloseHandle(phandle);
+ }
+
lock_ReleaseMutex(&smb_StartedLock);
return;
}
smbShutdownFlag = 1;
/* Hang up all sessions */
- memset((char *)ncbp, 0, sizeof(NCB));
+ memset(ncbp, 0, sizeof(NCB));
for (i = 1; i < numSessions; i++)
{
if (dead_sessions[i])
}
/* Delete Netbios name */
- memset((char *)ncbp, 0, sizeof(NCB));
+ memset(ncbp, 0, sizeof(NCB));
for (i = 0; i < lana_list.length; i++) {
if (lana_list.lana[i] == LANA_INVALID) continue;
ncbp->ncb_command = NCBDELNAME;
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
+ fprintf(stderr, "Shutdown: Netbios NCBDELNAME lana %d error code %d",
ncbp->ncb_lana_num, code);
}
fflush(stderr);
if (fidp->scp != NULL) {
cm_scache_t * scp;
+ lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
if (fidp->scp != NULL) {
scp = fidp->scp;
cm_ReleaseSCache(scp);
}
lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
}
}
}
lock_ReleaseWrite(&smb_rctLock);
smb_FreeNCB(ncbp);
- TlsFree(smb_TlsRequestSlot);
+
+ if (smb_monitorReqs) {
+ smb_ShutdownMonitor();
+ }
}
/* Get the UNC \\<servername>\<sharename> prefix. */
int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
{
int zilch;
- char output[1024];
+ char output[4196];
smb_vc_t *vcp;
-
+ smb_username_t *unp;
+ smb_waitingLockRequest_t *wlrp;
+
if (lock)
lock_ObtainRead(&smb_rctLock);
+ sprintf(output, "begin dumping smb_username_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (unp = usernamesp; unp; unp=unp->nextp)
+ {
+ cm_ucell_t *ucellp;
+
+ sprintf(output, "%s -- smb_unp=0x%p, refCount=%d, cm_userp=0x%p, flags=0x%x, logoff=%u, name=%S, machine=%S\r\n",
+ cookie, unp, unp->refCount, unp->userp, unp->flags, unp->last_logoff_t,
+ unp->name ? unp->name : _C("NULL"),
+ unp->machine ? unp->machine : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping cm_ucell_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ for ( ucellp = unp->userp->cellInfop; ucellp; ucellp = ucellp->nextp ) {
+ sprintf(output, " %s -- ucellp=0x%p, cellp=0x%p, flags=0x%x, tktLen=%04u, kvno=%03u, expires=%I64u, gen=%d, name=%s, cellname=%s\r\n",
+ cookie, ucellp, ucellp->cellp, ucellp->flags, ucellp->ticketLen, ucellp->kvno,
+ ucellp->expirationTime, ucellp->gen,
+ ucellp->userName,
+ ucellp->cellp->name);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, " done dumping cm_ucell_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ }
+ sprintf(output, "done dumping smb_username_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+ sprintf(output, "begin dumping smb_waitingLockRequest_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+ for ( wlrp = smb_allWaitingLocks; wlrp; wlrp = (smb_waitingLockRequest_t *) osi_QNext(&wlrp->q)) {
+ smb_waitingLock_t *lockp;
+
+ sprintf(output, "%s wlrp=0x%p vcp=0x%p, scp=0x%p, type=0x%x, start_t=0x%I64u msTimeout=0x%x\r\n",
+ cookie, wlrp, wlrp->vcp, wlrp->scp, wlrp->lockType, wlrp->start_t, wlrp->msTimeout);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_waitingLock_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (lockp = wlrp->locks; lockp; lockp = (smb_waitingLock_t *) osi_QNext(&lockp->q)) {
+ sprintf(output, " %s -- waitlockp=0x%p lockp=0x%p key=0x%I64x offset=0x%I64x length=0x%I64x state=0x%x\r\n",
+ cookie, lockp, lockp->lockp, lockp->key, lockp->LOffset.QuadPart, lockp->LLength.QuadPart, lockp->state);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_waitingLock_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping smb_waitingLockRequest_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
sprintf(output, "begin dumping smb_vc_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
+ smb_tid_t *tidp;
+ smb_user_t *userp;
sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping smb_fid_t\r\n");
+ sprintf(output, " begin dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (userp = vcp->usersp; userp; userp = userp->nextp) {
+ sprintf(output, " %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n",
+ cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ sprintf(output, " %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n",
+ cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+ tidp->pathname ? tidp->pathname : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
{
- sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
- cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
+ sprintf(output, " %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"),
fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping smb_fid_t\r\n");
+ sprintf(output, " done dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
-
+ smb_tid_t *tidp;
+ smb_user_t *userp;
+
sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
- cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+ cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping smb_fid_t\r\n");
+ sprintf(output, " begin dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (userp = vcp->usersp; userp; userp = userp->nextp) {
+ sprintf(output, " %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n",
+ cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ sprintf(output, " %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n",
+ cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+ tidp->pathname ? tidp->pathname : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
{
- sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
- cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
+ sprintf(output, " %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"),
fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping smb_fid_t\r\n");
+ sprintf(output, " done dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}