* directory or online at http://www.openafs.org/dl/license10.html
*/
-//#define NOTSERVICE 1
-#define LOG_PACKET 1
-
#include <afs/param.h>
#include <afs/stds.h>
-#ifndef DJGPP
#include <windows.h>
-#else
-#include <sys/timeb.h>
-#include <tzfile.h>
-#endif /* !DJGPP */
+#include <ntstatus.h>
#include <stddef.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <time.h>
-#include <osi.h>
-#include <ntstatus.h>
-
#include "afsd.h"
+#include <osi.h>
+#include <rx\rx.h>
+#include <rx/rx_prototypes.h>
+#include <WINNT\afsreg.h>
#include "smb.h"
#include "lanahelper.h"
/* These characters are illegal in Windows filenames */
static char *illegalChars = "\\/:*?\"<>|";
-BOOL isWindows2000 = FALSE;
-smb_vc_t *dead_vcp = NULL;
-smb_vc_t *active_vcp = NULL;
-
-/* TODO; logout mechanism needs to be thread-safe */
-char *loggedOutName = NULL;
-smb_user_t *loggedOutUserp = NULL;
-time_t loggedOutTime;
-int loggedOut = 0;
int smbShutdownFlag = 0;
int smb_LogoffTokenTransfer;
ULONG smb_lsaSecPackage;
LSA_STRING smb_lsaLogonOrigin;
-#define NCBmax MAXIMUM_WAIT_OBJECTS
-EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
+#define NCB_MAX MAXIMUM_WAIT_OBJECTS
+EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX];
EVENT_HANDLE **NCBreturns;
+EVENT_HANDLE **NCBShutdown;
EVENT_HANDLE *smb_ServerShutdown;
-DWORD NCBsessions[NCBmax];
-NCB *NCBs[NCBmax];
-struct smb_packet *bufs[NCBmax];
-
-#define Sessionmax MAXIMUM_WAIT_OBJECTS - 4
-EVENT_HANDLE SessionEvents[Sessionmax];
-unsigned short LSNs[Sessionmax];
-int lanas[Sessionmax];
-BOOL dead_sessions[Sessionmax];
+DWORD NCBsessions[NCB_MAX];
+NCB *NCBs[NCB_MAX];
+struct smb_packet *bufs[NCB_MAX];
+
+#define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4
+EVENT_HANDLE SessionEvents[SESSION_MAX];
+unsigned short LSNs[SESSION_MAX];
+int lanas[SESSION_MAX];
+BOOL dead_sessions[SESSION_MAX];
LANA_ENUM lana_list;
/* for raw I/O */
osi_mutex_t smb_RawBufLock;
-#ifdef DJGPP
-#define SMB_RAW_BUFS 4
-dos_ptr smb_RawBufs;
-int smb_RawBufSel[SMB_RAW_BUFS];
-#else
char *smb_RawBufs;
-#endif /* DJGPP */
#define SMB_MASKFLAG_TILDE 1
#define SMB_MASKFLAG_CASEFOLD 2
long code;
osi_hyper_t offset;
long count;
-#ifndef DJGPP
char *buf;
-#else
- dos_ptr buf;
-#endif /* DJGPP */
int writeMode;
long alreadyWritten;
} raw_write_cont_t;
/* global state about V3 protocols */
int smb_useV3; /* try to negotiate V3 */
-#ifndef DJGPP
-static showErrors = 1;
+static showErrors = 0;
/* MessageBox or something like it */
int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
-extern HANDLE WaitToTerminate;
-#endif /* DJGPP */
/* GMT time info:
* Time in Unix format of midnight, 1/1/1970 local time.
*/
time_t smb_localZero = 0;
+#define USE_NUMERIC_TIME_CONV 1
+
+#ifndef USE_NUMERIC_TIME_CONV
/* Time difference for converting to kludge-GMT */
-int smb_NowTZ;
+afs_uint32 smb_NowTZ;
+#endif /* USE_NUMERIC_TIME_CONV */
char *smb_localNamep = NULL;
smb_vc_t *smb_allVCsp;
+smb_vc_t *smb_deadVCsp;
smb_username_t *usernamesp = NULL;
-smb_waitingLock_t *smb_allWaitingLocks;
+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);
+ NCB *ncbp, raw_write_cont_t *rwcp);
void smb_NetbiosInit();
-#ifdef DJGPP
-#ifndef AFS_WIN95_ENV
-DWORD smb_ServerExceptionFilter(void);
-#endif
-
-extern char cm_HostName[];
-extern char cm_confDir[];
-#endif
-
-#ifdef DJGPP
-#define LPTSTR char *
-#define GetComputerName(str, sizep) \
- strcpy((str), cm_HostName); \
- *(sizep) = strlen(cm_HostName)
-#endif /* DJGPP */
#ifdef LOG_PACKET
void smb_LogPacket(smb_packet_t *packet);
#endif /* LOG_PACKET */
-extern char AFSConfigKeyName[];
char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
int smb_ServerDomainNameLength = 0;
/* Faux server GUID. This is never checked. */
GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+void smb_ResetServerPriority()
+{
+ void * p = TlsGetValue(smb_TlsRequestSlot);
+ if (p) {
+ free(p);
+ TlsSetValue(smb_TlsRequestSlot, NULL);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ }
+}
+
+void smb_SetRequestStartTime()
+{
+ time_t * tp = 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(), (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;
+ default: s = "unknown error";
+ }
+ return s;
+}
+
+
char * myCrt_Dispatch(int i)
{
switch (i)
return "(2d)ReceiveV3OpenX";
case 0x2e:
return "(2e)ReceiveV3ReadX";
+ case 0x2f:
+ return "(2f)ReceiveV3WriteX";
case 0x32:
return "(32)ReceiveV3Tran2A";
case 0x33:
default:
return "unknown SMB op-2";
case 0:
- return "S(00)CreateFile";
+ return "S(00)CreateFile_ReceiveTran2Open";
case 1:
- return "S(01)FindFirst";
+ return "S(01)FindFirst_ReceiveTran2SearchDir";
case 2:
- return "S(02)FindNext"; /* FindNext */
+ return "S(02)FindNext_ReceiveTran2SearchDir"; /* FindNext */
case 3:
return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
case 4:
- return "S(04)??";
+ return "S(04)SetFileSystem_ReceiveTran2SetFSInfo";
case 5:
- return "S(05)QueryFileInfo_ReceiveTran2QPathInfo";
+ return "S(05)QueryPathInfo_ReceiveTran2QPathInfo";
case 6:
- return "S(06)SetFileInfo_ReceiveTran2SetPathInfo";
+ return "S(06)SetPathInfo_ReceiveTran2SetPathInfo";
case 7:
- return "S(07)SetInfoHandle_ReceiveTran2QFileInfo";
+ return "S(07)QueryFileInfo_ReceiveTran2QFileInfo";
case 8:
- return "S(08)??_ReceiveTran2SetFileInfo";
+ return "S(08)SetFileInfo_ReceiveTran2SetFileInfo";
case 9:
- return "S(09)??_ReceiveTran2FSCTL";
+ return "S(09)_ReceiveTran2FSCTL";
case 10:
return "S(0a)_ReceiveTran2IOCTL";
case 11:
return "S(0d)_ReceiveTran2CreateDirectory";
case 14:
return "S(0e)_ReceiveTran2SessionSetup";
+ case 15:
+ return "S(0f)_QueryFileSystemInformationFid";
case 16:
return "S(10)_ReceiveTran2GetDfsReferral";
case 17:
unsigned int attrs;
if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
- scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID)
{
attrs = SMB_ATTR_DIRECTORY;
#ifdef SPECIAL_FOLDERS
attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
#endif /* SPECIAL_FOLDERS */
+ } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
} else
attrs = 0;
*/
#ifdef notdef
if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
+#else
+ if ((scp->unixModeBits & 0222) == 0)
+ attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
#endif
- if ((scp->unixModeBits & 0222) == 0)
- attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
return attrs;
}
return (int)num;
}
-#ifndef DJGPP
void ShowUnixTime(char *FuncName, time_t unixTime)
{
FILETIME ft;
osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
}
}
-#endif /* DJGPP */
-#ifndef DJGPP
/* Determine if we are observing daylight savings time */
void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
{
*/
*pDST = localDST.wHour != local.wHour;
}
-#else
-/* Determine if we are observing daylight savings time */
-void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
-{
- struct timeb t;
-
- ftime(&t);
- *pDST = t.dstflag;
- *pDstBias = -60; /* where can this be different? */
- *pBias = t.timezone;
-}
-#endif /* DJGPP */
-void CompensateForSmbClientLastWriteTimeBugs(long *pLastWriteTime)
+void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
{
BOOL dst; /* Will be TRUE if observing DST */
LONG dstBias; /* Offset from local time if observing DST */
*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.
local_tm = *(localtime(&t));
days = local_tm.tm_yday - gmt_tm.tm_yday;
- hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour
-#ifdef COMMENT
- /* There is a problem with DST immediately after the time change
- * which may continue to exist until the machine is rebooted
- */
- - (local_tm.tm_isdst ? 1 : 0)
-#endif /* COMMENT */
- ;
+ 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;
}
+#endif /* USE_NUMERIC_TIME_CONV */
+
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+{
+ // Note that LONGLONG is a 64-bit value
+ LONGLONG ll;
-#ifndef DJGPP
+ ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
+ largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
+ largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
+}
+#else
void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
{
struct tm *ltp;
SystemTimeToFileTime(&stm, largeTimep);
}
-#else /* DJGPP */
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+#endif /* USE_NUMERIC_TIME_CONV */
+
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
{
- /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
- /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
- LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
- LARGE_INTEGER ut;
- int leap_years = 89; /* leap years betw 1/1/1601 and 1/1/1970 */
-
- /* set ft to number of 100ns intervals betw 1/1/1601 and 1/1/1970 GMT */
- *ft = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years)
- * 24 * 60);
- *ft = LargeIntegerMultiplyByLong(*ft, 60);
- *ft = LargeIntegerMultiplyByLong(*ft, 10000000);
-
- /* add unix time */
- ut = ConvertLongToLargeInteger(unixTime);
- ut = LargeIntegerMultiplyByLong(ut, 10000000);
- *ft = LargeIntegerAdd(*ft, ut);
-}
-#endif /* !DJGPP */
+ // Note that LONGLONG is a 64-bit value
+ LONGLONG ll;
-#ifndef DJGPP
+ ll = largeTimep->dwHighDateTime;
+ ll <<= 32;
+ ll += largeTimep->dwLowDateTime;
+
+ ll -= 116444736000000000;
+ ll /= 10000000;
+
+ *unixTimep = (DWORD)ll;
+}
+#else /* USE_NUMERIC_TIME_CONV */
void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
{
SYSTEMTIME stm;
*unixTimep = mktime(<);
_timezone = save_timezone;
}
-#else /* DJGPP */
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
- /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
- /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
- LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
- LARGE_INTEGER a;
- int leap_years = 89;
-
- /* set to number of 100ns intervals betw 1/1/1601 and 1/1/1970 */
- a = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years) * 24 * 60);
- a = LargeIntegerMultiplyByLong(a, 60);
- a = LargeIntegerMultiplyByLong(a, 10000000);
-
- /* subtract it from ft */
- a = LargeIntegerSubtract(*ft, a);
+#endif /* USE_NUMERIC_TIME_CONV */
- /* divide down to seconds */
- *unixTimep = LargeIntegerDivideByLong(a, 10000000);
-}
-#endif /* !DJGPP */
-
-void smb_SearchTimeFromUnixTime(time_t *dosTimep, time_t unixTime)
+void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
{
struct tm *ltp;
int dosDate;
struct tm localJunk;
time_t t = unixTime;
- ltp = localtime((time_t*) &t);
+ ltp = localtime(&t);
/* if we fail, make up something */
if (!ltp) {
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);
- *dosTimep = (dosDate<<16) | dosTime;
+ *searchTimep = (dosDate<<16) | dosTime;
}
-void smb_UnixTimeFromSearchTime(time_t *unixTimep, time_t searchTime)
+void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
{
unsigned short dosDate;
unsigned short dosTime;
*unixTimep = mktime(&localTm);
}
-void smb_DosUTimeFromUnixTime(time_t *dosUTimep, time_t unixTime)
+void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
{
- *dosUTimep = unixTime - smb_localZero;
+ time_t diff_t = unixTime - smb_localZero;
+#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
+ osi_assert(diff_t < _UI32_MAX);
+#endif
+ *dosUTimep = (afs_uint32)diff_t;
}
-void smb_UnixTimeFromDosUTime(time_t *unixTimep, time_t dosTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
{
-#ifndef DJGPP
*unixTimep = dosTime + smb_localZero;
-#else /* DJGPP */
- /* dosTime seems to be already adjusted for GMT */
- *unixTimep = dosTime;
-#endif /* !DJGPP */
}
smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
smb_vc_t *vcp;
lock_ObtainWrite(&smb_rctLock);
- for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
- if (lsn == vcp->lsn && lana == vcp->lana) {
- vcp->refCount++;
+ for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+
+ if (lsn == vcp->lsn && lana == vcp->lana &&
+ !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ smb_HoldVCNoLock(vcp);
break;
}
}
if (!vcp && (flags & SMB_FLAG_CREATE)) {
vcp = malloc(sizeof(*vcp));
memset(vcp, 0, sizeof(*vcp));
- vcp->vcID = numVCs++;
- vcp->refCount = 1;
+ lock_ObtainWrite(&smb_globalLock);
+ vcp->vcID = ++numVCs;
+ lock_ReleaseWrite(&smb_globalLock);
+ vcp->magic = SMB_VC_MAGIC;
+ vcp->refCount = 2; /* smb_allVCsp and caller */
vcp->tidCounter = 1;
vcp->fidCounter = 1;
- vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
+ vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
vcp->nextp = smb_allVCsp;
smb_allVCsp = vcp;
lock_InitializeMutex(&vcp->mx, "vc_t mutex");
/* We must obtain a challenge for extended auth
* in case the client negotiates smb v3
*/
- NTSTATUS nts,ntsEx;
+ NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
- ULONG lsaRespSize;
+ ULONG lsaRespSize = 0;
lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
&lsaResp,
&lsaRespSize,
&ntsEx);
+ if (nts != STATUS_SUCCESS)
+ osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
+ nts, ntsEx, sizeof(lsaReq), lsaRespSize);
osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
}
else
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
+
+ if (numVCs >= CM_SESSION_RESERVED) {
+ lock_ObtainWrite(&smb_globalLock);
+ numVCs = 0;
+ lock_ReleaseWrite(&smb_globalLock);
+ osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
+ }
}
lock_ReleaseWrite(&smb_rctLock);
return vcp;
for(i=0; i<11; i++) {
tc = *maskp++;
- if (tc == '?' || tc == '*' || tc == '>') return 1;
+ if (tc == '?' || tc == '*' || tc == '>')
+ return 1;
}
return 0;
}
+void smb_ReleaseVCInternal(smb_vc_t *vcp)
+{
+ smb_vc_t **vcpp;
+ smb_vc_t * avcp;
+
+ vcp->refCount--;
+
+ if (vcp->refCount == 0) {
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ /* remove VCP from smb_deadVCsp */
+ for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+ if (*vcpp == vcp) {
+ *vcpp = vcp->nextp;
+ break;
+ }
+ }
+ lock_FinalizeMutex(&vcp->mx);
+ memset(vcp,0,sizeof(smb_vc_t));
+ free(vcp);
+ } else {
+ for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
+ if (avcp == vcp)
+ break;
+ }
+ osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
+ avcp?"not ":"",vcp, vcp->refCount);
+#ifdef DEBUG
+ GenerateMiniDump(NULL);
+#endif
+ /* This is a wrong. However, I suspect that there is an undercount
+ * and I don't want to release 1.4.1 in a state that will allow
+ * smb_vc_t objects to be deallocated while still in the
+ * smb_allVCsp list. The list is supposed to keep a reference
+ * to the smb_vc_t. Put it back.
+ */
+ vcp->refCount++;
+ }
+ }
+}
+
+void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+{
+ osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+ smb_ReleaseVCInternal(vcp);
+}
+
void smb_ReleaseVC(smb_vc_t *vcp)
{
lock_ObtainWrite(&smb_rctLock);
- osi_assert(vcp->refCount-- > 0);
+ osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
+ smb_ReleaseVCInternal(vcp);
lock_ReleaseWrite(&smb_rctLock);
}
+void smb_HoldVCNoLock(smb_vc_t *vcp)
+{
+ vcp->refCount++;
+ osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+}
+
void smb_HoldVC(smb_vc_t *vcp)
{
lock_ObtainWrite(&smb_rctLock);
vcp->refCount++;
+ osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
lock_ReleaseWrite(&smb_rctLock);
}
+void smb_CleanupDeadVC(smb_vc_t *vcp)
+{
+ smb_fid_t *fidpIter;
+ smb_fid_t *fidpNext;
+ unsigned short fid;
+ smb_tid_t *tidpIter;
+ smb_tid_t *tidpNext;
+ unsigned short tid;
+ smb_user_t *uidpIter;
+ smb_user_t *uidpNext;
+ smb_vc_t **vcpp;
+
+
+ lock_ObtainMutex(&vcp->mx);
+ if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
+ lock_ReleaseMutex(&vcp->mx);
+ osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
+ return;
+ }
+ vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
+ lock_ReleaseMutex(&vcp->mx);
+ osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
+
+ lock_ObtainWrite(&smb_rctLock);
+ /* remove VCP from smb_allVCsp */
+ for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+ if ((*vcpp)->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+ if (*vcpp == vcp) {
+ *vcpp = vcp->nextp;
+ vcp->nextp = smb_deadVCsp;
+ smb_deadVCsp = vcp;
+ /* Hold onto the reference until we are done with this function */
+ break;
+ }
+ }
+
+ for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
+ fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
+
+ if (fidpIter->delete)
+ continue;
+
+ fid = fidpIter->fid;
+ osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
+
+ smb_HoldFIDNoLock(fidpIter);
+ lock_ReleaseWrite(&smb_rctLock);
+
+ smb_CloseFID(vcp, fidpIter, NULL, 0);
+ smb_ReleaseFID(fidpIter);
+
+ lock_ObtainWrite(&smb_rctLock);
+ fidpNext = vcp->fidsp;
+ }
+
+ for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
+ tidpNext = tidpIter->nextp;
+ if (tidpIter->delete)
+ continue;
+ tidpIter->delete = 1;
+
+ tid = tidpIter->tid;
+ osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
+
+ smb_HoldTIDNoLock(tidpIter);
+ lock_ReleaseWrite(&smb_rctLock);
+
+ smb_ReleaseTID(tidpIter);
+
+ lock_ObtainWrite(&smb_rctLock);
+ tidpNext = vcp->tidsp;
+ }
+
+ for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
+ uidpNext = uidpIter->nextp;
+ if (uidpIter->delete)
+ continue;
+ uidpIter->delete = 1;
+
+ /* do not add an additional reference count for the smb_user_t
+ * as the smb_vc_t already is holding a reference */
+ lock_ReleaseWrite(&smb_rctLock);
+
+ smb_ReleaseUID(uidpIter);
+
+ lock_ObtainWrite(&smb_rctLock);
+ uidpNext = vcp->usersp;
+ }
+
+ /* The vcp is now on the deadVCsp list. We intentionally drop the
+ * reference so that the refcount can reach 0 and we can delete it */
+ smb_ReleaseVCNoLock(vcp);
+
+ lock_ReleaseWrite(&smb_rctLock);
+ osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
+}
+
smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
{
smb_tid_t *tidp;
lock_ObtainWrite(&smb_rctLock);
+ retry:
for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ if (tidp->refCount == 0 && tidp->delete) {
+ tidp->refCount++;
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_ReleaseTID(tidp);
+ lock_ObtainWrite(&smb_rctLock);
+ goto retry;
+ }
+
if (tid == tidp->tid) {
tidp->refCount++;
break;
tidp->nextp = vcp->tidsp;
tidp->refCount = 1;
tidp->vcp = vcp;
- vcp->refCount++;
+ smb_HoldVCNoLock(vcp);
vcp->tidsp = tidp;
lock_InitializeMutex(&tidp->mx, "tid_t mutex");
tidp->tid = tid;
return tidp;
}
+void smb_HoldTIDNoLock(smb_tid_t *tidp)
+{
+ tidp->refCount++;
+}
+
void smb_ReleaseTID(smb_tid_t *tidp)
{
smb_tid_t *tp;
smb_tid_t **ltpp;
cm_user_t *userp;
- smb_vc_t *vcp;
userp = NULL;
- vcp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(tidp->refCount-- > 0);
- if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
+ if (tidp->refCount == 0 && (tidp->delete)) {
ltpp = &tidp->vcp->tidsp;
for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
- if (tp == tidp) break;
+ if (tp == tidp)
+ break;
}
osi_assert(tp != NULL);
*ltpp = tp->nextp;
lock_FinalizeMutex(&tidp->mx);
userp = tidp->userp; /* remember to drop ref later */
- vcp = tidp->vcp;
+ tidp->userp = NULL;
+ smb_ReleaseVCNoLock(tidp->vcp);
+ tidp->vcp = NULL;
}
lock_ReleaseWrite(&smb_rctLock);
- if (userp) {
+ if (userp)
cm_ReleaseUser(userp);
- }
- if (vcp) {
- smb_ReleaseVC(vcp);
- }
}
smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
if (uid == uidp->userID) {
uidp->refCount++;
- osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL," VCP[%x] found-uid[%d] name[%s]",
- (int)vcp, uidp->userID,
- osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
+ osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
+ vcp, uidp->userID,
+ osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
break;
}
}
uidp = malloc(sizeof(*uidp));
memset(uidp, 0, sizeof(*uidp));
uidp->nextp = vcp->usersp;
- uidp->refCount = 1;
+ uidp->refCount = 2; /* one for the vcp and one for the caller */
uidp->vcp = vcp;
- vcp->refCount++;
+ smb_HoldVCNoLock(vcp);
vcp->usersp = uidp;
lock_InitializeMutex(&uidp->mx, "user_t mutex");
uidp->userID = uid;
- osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL,"VCP[%x] new-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp ? uidp->unp->name : ""));
+ osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
+ vcp, uidp->userID,
+ osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
}
lock_ReleaseWrite(&smb_rctLock);
return uidp;
}
-smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
+smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
{
smb_username_t *unp= NULL;
unp->machine = strdup(machine);
usernamesp = unp;
lock_InitializeMutex(&unp->mx, "username_t mutex");
+ if (flags & SMB_FLAG_AFSLOGON)
+ unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
}
+
lock_ReleaseWrite(&smb_rctLock);
return unp;
}
continue;
if (stricmp(uidp->unp->name, usern) == 0) {
uidp->refCount++;
- osi_LogEvent("AFS smb_FindUserByNameThisSession",NULL,"VCP[%x] uid[%d] match-name[%s]",(int)vcp,uidp->userID,usern);
+ osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
+ vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
break;
} else
continue;
lock_ReleaseWrite(&smb_rctLock);
return uidp;
}
+
+void smb_ReleaseUsername(smb_username_t *unp)
+{
+ smb_username_t *up;
+ smb_username_t **lupp;
+ cm_user_t *userp = NULL;
+ time_t now = osi_Time();
+
+ lock_ObtainWrite(&smb_rctLock);
+ osi_assert(unp->refCount-- > 0);
+ if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
+ (unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
+ lupp = &usernamesp;
+ for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
+ if (up == unp)
+ break;
+ }
+ osi_assert(up != NULL);
+ *lupp = up->nextp;
+ up->nextp = NULL; /* do not remove this */
+ lock_FinalizeMutex(&unp->mx);
+ userp = unp->userp;
+ free(unp->name);
+ free(unp->machine);
+ free(unp);
+ }
+ lock_ReleaseWrite(&smb_rctLock);
+
+ if (userp) {
+ cm_ReleaseUser(userp);
+ }
+}
+
+void smb_HoldUIDNoLock(smb_user_t *uidp)
+{
+ uidp->refCount++;
+}
+
void smb_ReleaseUID(smb_user_t *uidp)
{
smb_user_t *up;
smb_user_t **lupp;
- cm_user_t *userp;
- smb_vc_t *vcp;
+ smb_username_t *unp = NULL;
- userp = NULL;
- vcp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(uidp->refCount-- > 0);
- if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
+ if (uidp->refCount == 0) {
lupp = &uidp->vcp->usersp;
for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
- if (up == uidp) break;
+ if (up == uidp)
+ break;
}
osi_assert(up != NULL);
*lupp = up->nextp;
lock_FinalizeMutex(&uidp->mx);
- if (uidp->unp) {
- userp = uidp->unp->userp; /* remember to drop ref later */
- uidp->unp->userp = NULL;
- }
- vcp = uidp->vcp;
- uidp->vcp = NULL;
+ unp = uidp->unp;
+ smb_ReleaseVCNoLock(uidp->vcp);
+ uidp->vcp = NULL;
+ free(uidp);
}
lock_ReleaseWrite(&smb_rctLock);
- if (userp) {
- cm_ReleaseUserVCRef(userp);
- cm_ReleaseUser(userp);
- }
- if (vcp) {
- smb_ReleaseVC(vcp);
+
+ if (unp) {
+ if (unp->userp)
+ cm_ReleaseUserVCRef(unp->userp);
+ smb_ReleaseUsername(unp);
}
}
+cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
+{
+ cm_user_t *up = NULL;
+
+ if (!uidp)
+ return NULL;
+
+ lock_ObtainMutex(&uidp->mx);
+ if (uidp->unp) {
+ up = uidp->unp->userp;
+ cm_HoldUser(up);
+ }
+ lock_ReleaseMutex(&uidp->mx);
+
+ return up;
+}
+
+
/* retrieve a held reference to a user structure corresponding to an incoming
* request.
* corresponding release function is cm_ReleaseUser.
*/
-cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
+cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
{
smb_user_t *uidp;
- cm_user_t *up;
+ cm_user_t *up = NULL;
smb_t *smbp;
smbp = (smb_t *) inp;
uidp = smb_FindUID(vcp, smbp->uid, 0);
- if ((!uidp) || (!uidp->unp))
- return NULL;
-
- lock_ObtainMutex(&uidp->mx);
- up = uidp->unp->userp;
- cm_HoldUser(up);
- lock_ReleaseMutex(&uidp->mx);
+ if (!uidp)
+ return NULL;
+
+ up = smb_GetUserFromUID(uidp);
smb_ReleaseUID(uidp);
-
return up;
}
if (!tidp) {
*treepath = NULL;
} else {
- if(tidp->flags & SMB_TIDFLAG_IPC) {
+ if (tidp->flags & SMB_TIDFLAG_IPC) {
code = CM_ERROR_TIDIPC;
/* tidp->pathname would be NULL, but that's fine */
}
return 1;
}
-/* find a file ID. If we pass in 0 we select an used File ID.
+/* find a file ID. If we pass in 0 we select an unused File ID.
* If the SMB_FLAG_CREATE flag is set, we allocate a new
* smb_fid_t data structure if desired File ID cannot be found.
*/
retry:
for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+ if (fidp->refCount == 0 && fidp->delete) {
+ fidp->refCount++;
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_ReleaseFID(fidp);
+ lock_ObtainWrite(&smb_rctLock);
+ goto retry;
+ }
if (fid == fidp->fid) {
if (newFid) {
fid++;
- if (fid == 0)
+ if (fid == 0xFFFF) {
+ osi_Log1(smb_logp,
+ "New FID number wraps on vcp 0x%x", vcp);
fid = 1;
+ }
goto retry;
}
fidp->refCount++;
break;
}
}
+
if (!fidp && (flags & SMB_FLAG_CREATE)) {
char eventName[MAX_PATH];
EVENT_HANDLE event;
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
thrd_CloseHandle(event);
fid++;
- if (fid == 0)
+ if (fid == 0xFFFF) {
+ osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
fid = 1;
+ }
goto retry;
}
osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
fidp->refCount = 1;
fidp->vcp = vcp;
- vcp->refCount++;
+ smb_HoldVCNoLock(vcp);
lock_InitializeMutex(&fidp->mx, "fid_t mutex");
fidp->fid = fid;
fidp->curr_chunk = fidp->prev_chunk = -2;
fidp->raw_write_event = event;
if (newFid) {
vcp->fidCounter = fid+1;
- if (vcp->fidCounter == 0)
+ if (vcp->fidCounter == 0xFFFF) {
+ osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
+ vcp);
vcp->fidCounter = 1;
+ }
+ }
+ }
+
+ lock_ReleaseWrite(&smb_rctLock);
+ return fidp;
+}
+
+smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
+{
+ smb_fid_t *fidp = NULL;
+ int newFid = 0;
+
+ if (!scp)
+ return NULL;
+
+ lock_ObtainWrite(&smb_rctLock);
+ for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+ if (scp == fidp->scp) {
+ fidp->refCount++;
+ break;
}
}
lock_ReleaseWrite(&smb_rctLock);
return fidp;
}
+void smb_HoldFIDNoLock(smb_fid_t *fidp)
+{
+ fidp->refCount++;
+}
+
void smb_ReleaseFID(smb_fid_t *fidp)
{
- cm_scache_t *scp;
+ cm_scache_t *scp = NULL;
+ cm_user_t *userp = NULL;
smb_vc_t *vcp = NULL;
smb_ioctl_t *ioctlp;
- if (!fidp)
- return;
-
- scp = NULL;
+ lock_ObtainMutex(&fidp->mx);
lock_ObtainWrite(&smb_rctLock);
osi_assert(fidp->refCount-- > 0);
- if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
+ if (fidp->refCount == 0 && (fidp->delete)) {
vcp = fidp->vcp;
- if (!(fidp->flags & SMB_FID_IOCTL))
- scp = fidp->scp;
- osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
+ fidp->vcp = NULL;
+ scp = fidp->scp; /* release after lock is released */
+ fidp->scp = NULL;
+ userp = fidp->userp;
+ fidp->userp = NULL;
+
+ if (vcp->fidsp)
+ osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
thrd_CloseHandle(fidp->raw_write_event);
/* and see if there is ioctl stuff to free */
ioctlp = fidp->ioctlp;
if (ioctlp) {
- if (ioctlp->prefix) cm_FreeSpace(ioctlp->prefix);
- if (ioctlp->inAllocp) free(ioctlp->inAllocp);
- if (ioctlp->outAllocp) free(ioctlp->outAllocp);
+ if (ioctlp->prefix)
+ cm_FreeSpace(ioctlp->prefix);
+ if (ioctlp->inAllocp)
+ free(ioctlp->inAllocp);
+ if (ioctlp->outAllocp)
+ free(ioctlp->outAllocp);
free(ioctlp);
}
-
+ lock_ReleaseMutex(&fidp->mx);
+ lock_FinalizeMutex(&fidp->mx);
free(fidp);
- /* do not call smb_ReleaseVC() because we already have the lock */
- vcp->refCount--;
+ if (vcp)
+ smb_ReleaseVCNoLock(vcp);
+ } else {
+ lock_ReleaseMutex(&fidp->mx);
}
lock_ReleaseWrite(&smb_rctLock);
/* now release the scache structure */
if (scp)
cm_ReleaseSCache(scp);
+
+ if (userp)
+ cm_ReleaseUser(userp);
}
/*
char VNComputerName[] = "%COMPUTERNAME%";
char VNLCComputerName[] = "%LCCOMPUTERNAME%";
-#ifdef DJGPP
-/* List available shares */
-int smb_ListShares()
-{
- char sbmtpath[256];
- char pathName[256];
- char shareBuf[4096];
- int num_shares=0;
- char *this_share;
- int len;
- char *p;
- int print_afs = 0;
- int code;
-
- /*strcpy(shareNameList[num_shares], "all");
- strcpy(pathNameList[num_shares++], "/afs");*/
- fprintf(stderr, "The following shares are available:\n");
- fprintf(stderr, "Share Name (AFS Path)\n");
- fprintf(stderr, "---------------------\n");
- fprintf(stderr, "\\\\%s\\%-16s (%s)\n", smb_localNamep, "ALL", cm_mountRoot);
-
-#ifndef DJGPP
- code = GetWindowsDirectory(sbmtpath, sizeof(sbmtpath));
- if (code == 0 || code > sizeof(sbmtpath)) return -1;
-#else
- strcpy(sbmtpath, cm_confDir);
-#endif /* !DJGPP */
- strcat(sbmtpath, "/afsdsbmt.ini");
- len = GetPrivateProfileString("AFS Submounts", NULL, NULL,
- shareBuf, sizeof(shareBuf),
- sbmtpath);
- if (len == 0) {
- return num_shares;
- }
-
- this_share = shareBuf;
- do
- {
- print_afs = 0;
- /*strcpy(shareNameList[num_shares], this_share);*/
- len = GetPrivateProfileString("AFS Submounts", this_share,
- NULL,
- pathName, 256,
- sbmtpath);
- if (!len)
- return num_shares;
- p = pathName;
- if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) != 0)
- print_afs = 1;
- while (*p) {
- if (*p == '\\') *p = '/'; /* change to / */
- p++;
- }
-
- fprintf(stderr, "\\\\%s\\%-16s (%s%s)\n",
- smb_localNamep, this_share, (print_afs ? cm_mountRoot : "\0"),
- pathName);
- num_shares++;
- while (*this_share != 0) this_share++; /* find next NUL */
- this_share++; /* skip past the NUL */
- } while (*this_share != 0); /* stop at final NUL */
-
- return num_shares;
-}
-#endif /* DJGPP */
typedef struct smb_findShare_rock {
char * shareName;
char *var;
char temp[1024];
DWORD sizeTemp;
-#ifdef DJGPP
- char sbmtpath[MAX_PATH];
-#endif
char *p, *q;
HKEY parmKey;
DWORD code;
* This is to allow sites that want to restrict access to the
* world to do so.
*/
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
0, KEY_QUERY_VALUE, &parmKey);
if (code == ERROR_SUCCESS) {
len = sizeof(allSubmount);
return 0;
}
-#ifndef DJGPP
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
0, KEY_QUERY_VALUE, &parmKey);
if (code == ERROR_SUCCESS) {
len = sizeof(pathName);
} else {
len = 0;
}
-#else /* DJGPP */
- strcpy(sbmtpath, cm_confDir);
- strcat(sbmtpath, "/afsdsbmt.ini");
- len = GetPrivateProfileString("AFS Submounts", shareName, "",
- pathName, sizeof(pathName), sbmtpath);
-#endif /* !DJGPP */
if (len != 0 && len != sizeof(pathName) - 1) {
/* We can accept either unix or PC style AFS pathnames. Convert
* Unix-style to PC style here for internal use.
vrock.match = NULL;
vrock.matchType = 0;
- cm_HoldSCache(cm_rootSCachep);
- code = cm_ApplyDir(cm_rootSCachep, smb_FindShareProc, &vrock, &thyper,
+ 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_rootSCachep);
+ cm_ReleaseSCache(cm_data.rootSCachep);
if (vrock.matchType) {
sprintf(pathName,"/%s/",vrock.match);
/* Get the full name for this cell */
code = cm_SearchCellFile(p, temp, 0, 0);
#ifdef AFS_AFSDB_ENV
- if (code && cm_dnsEnabled) {
+ if (code && cm_dnsEnabled) {
int ttl;
code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
}
int retval = CSC_POLICY_MANUAL;
RegCreateKeyEx( HKEY_LOCAL_MACHINE,
- "SOFTWARE\\OpenAFS\\Client\\CSCPolicy",
+ AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
0,
"AFS",
REG_OPTION_NON_VOLATILE,
if (dsp != smb_firstDirSearchp) {
/* move to head of LRU queue, too, if we're not already there */
if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
- smb_lastDirSearchp = (smb_dirSearch_t *)
- osi_QPrev(&dsp->q);
+ smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
if (!smb_lastDirSearchp)
break;
}
}
+
+ if (dsp == NULL) {
+ osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
+ for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
+ osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
+ }
+ }
return dsp;
}
if (dsp->flags & SMB_DIRSEARCH_BULKST) {
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
- dsp->scp->bulkStatProgress = hones;
+ dsp->scp->bulkStatProgress = hzero;
}
lock_ReleaseMutex(&dsp->scp->mx);
}
/* Must be called with the smb_globalLock held */
void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
{
- cm_scache_t *scp;
-
- scp = NULL;
+ cm_scache_t *scp = NULL;
lock_ObtainMutex(&dsp->mx);
osi_assert(dsp->refCount-- > 0);
lock_ReleaseMutex(&dsp->mx);
}
/* do this now to avoid spurious locking hierarchy creation */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
}
void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
*/
if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
/* hold and delete */
+ lock_ObtainMutex(&tp->mx);
tp->flags |= SMB_DIRSEARCH_DELETE;
+ lock_ReleaseMutex(&tp->mx);
victimsp[victimCount++] = tp;
tp->refCount++;
}
smb_dirSearch_t *dsp;
int counter;
int maxAllowed;
+ int start;
+ int wrapped = 0;
lock_ObtainWrite(&smb_globalLock);
counter = 0;
/* what's the biggest ID allowed in this version of the protocol */
maxAllowed = isV3 ? 65535 : 255;
+ if (smb_dirSearchCounter > maxAllowed)
+ smb_dirSearchCounter = 1;
+
+ start = smb_dirSearchCounter;
while (1) {
/* twice so we have enough tries to find guys we GC after one pass;
if (smb_dirSearchCounter > maxAllowed) {
smb_dirSearchCounter = 1;
- smb_GCDirSearches(isV3); /* GC some */
- }
+ }
+ if (smb_dirSearchCounter == start) {
+ if (wrapped)
+ smb_GCDirSearches(isV3);
+ wrapped++;
+ }
dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
if (dsp) {
/* don't need to watch for refcount zero and deleted, since
dsp = malloc(sizeof(*dsp));
memset(dsp, 0, sizeof(*dsp));
- osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
- if (!smb_lastDirSearchp)
- smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
dsp->cookie = smb_dirSearchCounter;
++smb_dirSearchCounter;
dsp->refCount = 1;
lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
dsp->lastTime = osi_Time();
+ osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ if (!smb_lastDirSearchp)
+ smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
break;
}
lock_ReleaseWrite(&smb_globalLock);
static smb_packet_t *GetPacket(void)
{
smb_packet_t *tbp;
-#ifdef DJGPP
- unsigned int npar, seg, tb_sel;
-#endif
lock_ObtainWrite(&smb_globalLock);
tbp = smb_packetFreeListp;
smb_packetFreeListp = tbp->nextp;
lock_ReleaseWrite(&smb_globalLock);
if (!tbp) {
-#ifndef DJGPP
tbp = calloc(65540,1);
-#else /* DJGPP */
- tbp = malloc(sizeof(smb_packet_t));
-#endif /* !DJGPP */
tbp->magic = SMB_PACKETMAGIC;
tbp->ncbp = NULL;
tbp->vcp = NULL;
tbp->flags = 0;
tbp->spacep = NULL;
-#ifdef DJGPP
- npar = SMB_PACKETSIZE >> 4; /* number of paragraphs */
- {
- signed int retval =
- __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
- if (retval == -1) {
- osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS memory",
- npar);
- osi_panic("",__FILE__,__LINE__);
- }
- else {
- osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X",
- npar, retval);
- seg = retval;
- }
- }
- tbp->dos_pkt = (seg * 16) + 0; /* DOS physical address */
- tbp->dos_pkt_sel = tb_sel;
-#endif /* DJGPP */
}
osi_assert(tbp->magic == SMB_PACKETMAGIC);
smb_packet_t *tbp;
tbp = GetPacket();
memcpy(tbp, pkt, sizeof(smb_packet_t));
- tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
+ tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+ if (tbp->vcp)
+ smb_HoldVC(tbp->vcp);
return tbp;
}
{
smb_ncb_t *tbp;
NCB *ncbp;
-#ifdef DJGPP
- unsigned int npar, seg, tb_sel;
-#endif /* DJGPP */
lock_ObtainWrite(&smb_globalLock);
tbp = smb_ncbFreeListp;
smb_ncbFreeListp = tbp->nextp;
lock_ReleaseWrite(&smb_globalLock);
if (!tbp) {
-#ifndef DJGPP
tbp = calloc(sizeof(*tbp),1);
-#else /* DJGPP */
- tbp = malloc(sizeof(*tbp));
- npar = (sizeof(NCB)+15) >> 4; /* number of paragraphs */
- {
- signed int retval =
- __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
- if (retval == -1) {
- osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS mem in GetNCB",
- npar);
- osi_panic("",__FILE__,__LINE__);
- } else {
- osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
- npar, retval);
- seg = retval;
- }
- }
- tbp->dos_ncb = (seg * 16) + 0; /* DOS physical address */
- tbp->dos_ncb_sel = tb_sel;
-#endif /* !DJGPP */
tbp->magic = SMB_NCBMAGIC;
}
memset(&tbp->ncb, 0, sizeof(NCB));
ncbp = &tbp->ncb;
-#ifdef DJGPP
- dos_memset(tbp->dos_ncb, 0, sizeof(NCB));
-#endif /* DJGPP */
return ncbp;
}
void smb_FreePacket(smb_packet_t *tbp)
{
+ smb_vc_t * vcp = NULL;
osi_assert(tbp->magic == SMB_PACKETMAGIC);
lock_ObtainWrite(&smb_globalLock);
smb_packetFreeListp = tbp;
tbp->magic = SMB_PACKETMAGIC;
tbp->ncbp = NULL;
+ vcp = tbp->vcp;
tbp->vcp = NULL;
tbp->resumeCode = 0;
tbp->inCount = 0;
tbp->ncb_length = 0;
tbp->flags = 0;
lock_ReleaseWrite(&smb_globalLock);
+
+ if (vcp)
+ smb_ReleaseVC(vcp);
}
static void FreeNCB(NCB *bufferp)
parmCount = *smbp->wctp;
if (parm >= parmCount) {
- char s[100];
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-#endif
- sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+ char s[100];
+
+ sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+ parm, parmCount, smbp->ncb_length);
+ osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
parm, parmCount, smbp->ncb_length);
-#ifndef DJGPP
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
- 1, smbp->ncb_length, ptbuf, smbp);
- DeregisterEventSource(h);
-#endif
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
+ __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
osi_panic(s, __FILE__, __LINE__);
}
parmDatap = smbp->wctp + (2*parm) + 1;
}
/* return the parm'th parameter in the smbp packet */
+unsigned int smb_GetSMBParmLong(smb_packet_t *smbp, int parm)
+{
+ int parmCount;
+ unsigned char *parmDatap;
+
+ parmCount = *smbp->wctp;
+
+ if (parm + 1 >= parmCount) {
+ char s[100];
+
+ sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+ parm, parmCount, smbp->ncb_length);
+ osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
+ parm, parmCount, smbp->ncb_length);
+ LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
+ __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
+ osi_panic(s, __FILE__, __LINE__);
+ }
+ parmDatap = smbp->wctp + (2*parm) + 1;
+
+ return parmDatap[0] + (parmDatap[1] << 8) + (parmDatap[2] << 16) + (parmDatap[3] << 24);
+}
+
+/* return the parm'th parameter in the smbp packet */
unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
{
int parmCount;
if (parm * 2 + offset >= parmCount * 2) {
char s[100];
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-#endif
+
sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
parm, offset, parmCount, smbp->ncb_length);
-#ifndef DJGPP
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
- 1, smbp->ncb_length, ptbuf, smbp);
- DeregisterEventSource(h);
-#endif
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET,
+ __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
+ osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
+ parm, offset, parmCount, smbp->ncb_length);
osi_panic(s, __FILE__, __LINE__);
}
parmDatap = smbp->wctp + (2*parm) + 1 + offset;
*parmDatap++ = parmValue & 0xff;
*parmDatap++ = (parmValue>>8) & 0xff;
*parmDatap++ = (parmValue>>16) & 0xff;
- *parmDatap++ = (parmValue>>24) & 0xff;
+ *parmDatap = (parmValue>>24) & 0xff;
}
void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
outp->res[1] = inSmbp->res[1];
op->inCom = inSmbp->com;
}
- outp->reb = 0x80; /* SERVER_RESP */
+ outp->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
/* copy fields in generic packet area */
long code = 0;
unsigned char *tp;
int localNCB = 0;
-#ifdef DJGPP
- dos_ptr dos_ncb;
-#endif /* DJGPP */
ncbp = inp->ncbp;
if (ncbp == NULL) {
ncbp = GetNCB();
localNCB = 1;
}
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
memset((char *)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 */
extra += tp[0] + (tp[1]<<8);
- extra += ((unsigned int)inp->wctp - (unsigned int)inp->data); /* distance to last wct field */
+ extra += (unsigned int)(inp->wctp - inp->data); /* distance to last wct field */
extra += 3; /* wct and length fields */
ncbp->ncb_length = extra; /* bytes to send */
ncbp->ncb_lsn = (unsigned char) vcp->lsn; /* vc to use */
ncbp->ncb_lana_num = vcp->lana;
ncbp->ncb_command = NCBSEND; /* op means send data */
-#ifndef DJGPP
ncbp->ncb_buffer = (char *) inp;/* packet */
code = Netbios(ncbp);
-#else /* DJGPP */
- ncbp->ncb_buffer = inp->dos_pkt;/* packet */
- ((smb_ncb_t*)ncbp)->orig_pkt = inp;
-
- /* copy header information from virtual to DOS address space */
- dosmemput((char*)inp, SMB_PACKETSIZE, inp->dos_pkt);
- code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
- if (code != 0)
- osi_Log1(smb_logp, "SendPacket failure code %d", code);
+ if (code != 0) {
+ const char * s = ncb_error_string(code);
+ osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
+
+ lock_ObtainMutex(&vcp->mx);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
+ }
if (localNCB)
FreeNCB(ncbp);
NTStatus = 0xC000000FL; /* No such file */
}
else if (code == CM_ERROR_TIMEDOUT) {
+#ifdef COMMENT
NTStatus = 0xC00000CFL; /* Sharing Paused */
+#else
+ NTStatus = 0x00000102L; /* Timeout */
+#endif
}
else if (code == CM_ERROR_RETRY) {
NTStatus = 0xC000022DL; /* Retry */
}
else if (code == CM_ERROR_READONLY) {
NTStatus = 0xC00000A2L; /* Write protected */
- }
+ }
else if (code == CM_ERROR_NOSUCHFILE) {
NTStatus = 0xC000000FL; /* No such file */
}
else if (code == CM_ERROR_WOULDBLOCK) {
NTStatus = 0xC0000055L; /* Lock not granted */
}
+ else if (code == CM_ERROR_SHARING_VIOLATION) {
+ NTStatus = 0xC0000043L; /* Sharing violation */
+ }
+ else if (code == CM_ERROR_LOCK_CONFLICT) {
+ NTStatus = 0xC0000054L; /* Lock conflict */
+ }
else if (code == CM_ERROR_PARTIALWRITE) {
NTStatus = 0xC000007FL; /* Disk full */
}
NTStatus = 0xC0000022L; /* Access Denied */
#endif
}
- else {
+ else if (code == CM_ERROR_PATH_NOT_COVERED) {
+ NTStatus = 0xC0000257L; /* Path Not Covered */
+ }
+#ifdef COMMENT
+ else if (code == CM_ERROR_ALLBUSY) {
+ NTStatus = 0xC00000BFL; /* Network Busy */
+ }
+ else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+ NTStatus = 0xC0000350L; /* Remote Host Down */
+ }
+#else
+ /* we do not want to be telling the SMB/CIFS client that
+ * the AFS Client Service is busy or down.
+ */
+ else if (code == CM_ERROR_ALLBUSY ||
+ code == CM_ERROR_ALLOFFLINE ||
+ code == CM_ERROR_ALLDOWN) {
+ NTStatus = 0xC00000BEL; /* Bad Network Path */
+ }
+#endif
+ else if (code == RXKADUNKNOWNKEY) {
+ NTStatus = 0xC0000322L; /* Bad Kerberos key */
+ } else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
class = 1;
error = 33; /* lock conflict */
}
+ else if (code == CM_ERROR_LOCK_CONFLICT) {
+ class = 1;
+ error = 33; /* lock conflict */
+ }
+ else if (code == CM_ERROR_SHARING_VIOLATION) {
+ class = 1;
+ error = 33; /* lock conflict */
+ }
else if (code == CM_ERROR_NOFILES) {
class = 1;
error = 18; /* no files in search */
class = 2;
error = 2; /* bad password */
}
+ else if (code == CM_ERROR_PATH_NOT_COVERED) {
+ class = 2;
+ error = 3; /* bad path */
+ }
else {
class = 2;
error = 1;
osi_hyper_t offset;
long count, minCount, finalCount;
unsigned short fd;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp = NULL;
NCB *ncbp;
int rc;
-#ifndef DJGPP
char *rawBuf = NULL;
-#else
- dos_ptr rawBuf = NULL;
- dos_ptr dos_ncb;
-#endif /* DJGPP */
rawBuf = NULL;
finalCount = 0;
fd = smb_GetSMBParm(inp, 0);
count = smb_GetSMBParm(inp, 3);
minCount = smb_GetSMBParm(inp, 4);
- offset.HighPart = 0; /* too bad */
offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
- osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
- fd, offset.LowPart, count);
+ if (*inp->wctp == 10) {
+ /* we were sent a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+ offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
+
+ if (LargeIntegerLessThanZero(offset)) {
+ osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
+ goto send1;
+ }
+#else
+ if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
+ osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset. Dropping request.");
+ goto send1;
+ } else {
+ offset.HighPart = 0;
+ }
+#endif
+ } else {
+ /* we were sent a request with 32-bit file offsets */
+ offset.HighPart = 0;
+ }
+
+ osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
+ fd, offset.HighPart, offset.LowPart, count);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp)
goto send1;
+ pid = ((smb_t *) inp)->pid;
+ {
+ LARGE_INTEGER LOffset, LLength;
+ cm_key_t key;
+
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+ LOffset.HighPart = offset.HighPart;
+ LOffset.LowPart = offset.LowPart;
+ LLength.HighPart = 0;
+ LLength.LowPart = count;
+
+ lock_ObtainMutex(&fidp->scp->mx);
+ code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+ lock_ReleaseMutex(&fidp->scp->mx);
+ }
+ if (code) {
+ goto send1a;
+ }
+
lock_ObtainMutex(&smb_RawBufLock);
if (smb_RawBufs) {
/* Get a raw buf, from head of list */
rawBuf = smb_RawBufs;
-#ifndef DJGPP
smb_RawBufs = *(char **)smb_RawBufs;
-#else /* DJGPP */
- smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
-#endif /* !DJGPP */
}
lock_ReleaseMutex(&smb_RawBufLock);
if (!rawBuf)
goto send1a;
+ lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL)
{
-#ifndef DJGPP
+ lock_ReleaseMutex(&fidp->mx);
rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
-#else
- rc = smb_IoctlReadRaw(fidp, vcp, inp, outp, rawBuf);
-#endif
if (rawBuf) {
/* Give back raw buffer */
lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
*((char **) rawBuf) = smb_RawBufs;
-#else /* DJGPP */
- _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
smb_RawBufs = rawBuf;
lock_ReleaseMutex(&smb_RawBufLock);
smb_ReleaseFID(fidp);
return rc;
}
-
- userp = smb_GetUser(vcp, inp);
+ lock_ReleaseMutex(&fidp->mx);
+
+ userp = smb_GetUserFromVCP(vcp, inp);
-#ifndef DJGPP
code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
-#else /* DJGPP */
- /* have to give ReadData flag so it will treat buffer as DOS mem. */
- code = smb_ReadData(fidp, &offset, count, (unsigned char *)rawBuf,
- userp, &finalCount, TRUE /* rawFlag */);
-#endif /* !DJGPP */
if (code != 0)
goto send;
send1:
ncbp = outp->ncbp;
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
memset((char *)ncbp, 0, sizeof(NCB));
ncbp->ncb_length = (unsigned short) finalCount;
ncbp->ncb_command = NCBSEND;
ncbp->ncb_buffer = rawBuf;
-#ifndef DJGPP
code = Netbios(ncbp);
-#else /* DJGPP */
- code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
if (code != 0)
osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
if (rawBuf) {
/* Give back raw buffer */
lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
*((char **) rawBuf) = smb_RawBufs;
-#else /* DJGPP */
- _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
smb_RawBufs = rawBuf;
lock_ReleaseMutex(&smb_RawBufLock);
int coreProtoIndex;
int v3ProtoIndex;
int NTProtoIndex;
+ int VistaProtoIndex;
int protoIndex; /* index we're using */
int namex;
int dbytes;
char protocol_array[10][1024]; /* protocol signature of the client */
int caps; /* capabilities */
time_t unixTime;
- time_t dosTime;
+ afs_uint32 dosTime;
TIME_ZONE_INFORMATION tzi;
osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
ongoingOps - 1);
- if (!isGateway) {
- if (active_vcp) {
- DWORD now = GetCurrentTime();
- if (now - last_msg_time >= 30000
- && now - last_msg_time <= 90000) {
- osi_Log1(smb_logp,
- "Setting dead_vcp %x", active_vcp);
- if (dead_vcp) {
- smb_ReleaseVC(dead_vcp);
- osi_Log1(smb_logp,
- "Previous dead_vcp %x", dead_vcp);
- }
- smb_HoldVC(active_vcp);
- dead_vcp = active_vcp;
- dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- }
- }
- }
-
- inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
namep = smb_GetSMBData(inp, &dbytes);
namex = 0;
coreProtoIndex = -1; /* not found */
v3ProtoIndex = -1;
NTProtoIndex = -1;
+ VistaProtoIndex = -1;
while(namex < dbytes) {
osi_Log1(smb_logp, "Protocol %s",
osi_LogSaveString(smb_logp, namep+1));
else if (smb_useV3 && strcmp("NT LM 0.12", namep+1) == 0) {
NTProtoIndex = tcounter;
}
+ else if (smb_useV3 && strcmp("SMB 2.001", namep+1) == 0) {
+ VistaProtoIndex = tcounter;
+ }
/* compute size of protocol entry */
- entryLength = strlen(namep+1);
+ entryLength = (int)strlen(namep+1);
entryLength += 2; /* 0x02 bytes and null termination */
/* advance over this protocol entry */
tcounter++; /* which proto entry we're looking at */
}
- if (NTProtoIndex != -1) {
+ lock_ObtainMutex(&vcp->mx);
+#if 0
+ if (VistaProtoIndex != -1) {
+ protoIndex = VistaProtoIndex;
+ vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
+ } else
+#endif
+ if (NTProtoIndex != -1) {
protoIndex = NTProtoIndex;
vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
}
vcp->flags |= SMB_VCFLAG_USECORE;
}
else protoIndex = -1;
+ lock_ReleaseMutex(&vcp->mx);
if (protoIndex == -1)
return CM_ERROR_INVAL;
- else if (NTProtoIndex != -1) {
+ else if (VistaProtoIndex != 1 || NTProtoIndex != -1) {
smb_SetSMBParm(outp, 0, protoIndex);
if (smb_authType != SMB_AUTH_NONE) {
smb_SetSMBParmByte(outp, 1,
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
#endif
+#ifdef AFS_LARGEFILES
+ NTNEGOTIATE_CAPABILITY_LARGEFILES |
+#endif
NTNEGOTIATE_CAPABILITY_NTFIND |
NTNEGOTIATE_CAPABILITY_RAWMODE |
NTNEGOTIATE_CAPABILITY_NTSMB;
return 0;
}
+void smb_CheckVCs(void)
+{
+ smb_vc_t * vcp, *nextp;
+ smb_packet_t * outp = GetPacket();
+ smb_t *smbp;
+
+ lock_ObtainWrite(&smb_rctLock);
+ for ( vcp=smb_allVCsp, nextp=NULL; vcp; vcp = nextp )
+ {
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
+
+ nextp = vcp->nextp;
+
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+ continue;
+
+ smb_HoldVCNoLock(vcp);
+ if (nextp)
+ smb_HoldVCNoLock(nextp);
+ smb_FormatResponsePacket(vcp, NULL, outp);
+ smbp = (smb_t *)outp;
+ outp->inCom = smbp->com = 0x2b /* Echo */;
+ smbp->tid = 0xFFFF;
+ smbp->pid = 0;
+ smbp->uid = 0;
+ smbp->mid = 0;
+ smbp->res[0] = 0;
+ smbp->res[1] = 0;
+
+ smb_SetSMBParm(outp, 0, 0);
+ smb_SetSMBDataLength(outp, 0);
+ lock_ReleaseWrite(&smb_rctLock);
+
+ smb_SendPacket(vcp, outp);
+
+ lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseVCNoLock(vcp);
+ if (nextp)
+ smb_ReleaseVCNoLock(nextp);
+ }
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_FreePacket(outp);
+}
+
void smb_Daemon(void *parmp)
{
afs_uint32 count = 0;
+ smb_username_t **unpp;
+ time_t now;
while(smbShutdownFlag == 0) {
count++;
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();
#endif
- }
+
+ smb_CheckVCs();
+ }
+
+ /* GC smb_username_t objects that will no longer be used */
+ now = osi_Time();
+ lock_ObtainWrite(&smb_rctLock);
+ for ( unpp=&usernamesp; *unpp; ) {
+ int delete = 0;
+ smb_username_t *unp;
+
+ lock_ObtainMutex(&(*unpp)->mx);
+ if ( (*unpp)->refCount > 0 ||
+ ((*unpp)->flags & SMB_USERNAMEFLAG_AFSLOGON) ||
+ !((*unpp)->flags & SMB_USERNAMEFLAG_LOGOFF))
+ ;
+ else if (!smb_LogoffTokenTransfer ||
+ ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
+ delete = 1;
+ lock_ReleaseMutex(&(*unpp)->mx);
+
+ if (delete) {
+ cm_user_t * userp;
+
+ unp = *unpp;
+ *unpp = unp->nextp;
+ unp->nextp = NULL;
+ lock_FinalizeMutex(&unp->mx);
+ userp = unp->userp;
+ free(unp->name);
+ free(unp->machine);
+ free(unp);
+ if (userp) {
+ lock_ReleaseWrite(&smb_rctLock);
+ cm_ReleaseUser(userp);
+ lock_ObtainWrite(&smb_rctLock);
+ }
+ } else {
+ unpp = &(*unpp)->nextp;
+ }
+ }
+ lock_ReleaseWrite(&smb_rctLock);
+
/* XXX GC dir search entries */
}
}
void smb_WaitingLocksDaemon()
{
- smb_waitingLock_t *wL, *nwL;
+ smb_waitingLockRequest_t *wlRequest, *nwlRequest;
+ smb_waitingLock_t *wl, *wlNext;
int first;
smb_vc_t *vcp;
smb_packet_t *inp, *outp;
NCB *ncbp;
long code = 0;
- while (1) {
+ while (smbShutdownFlag == 0) {
lock_ObtainWrite(&smb_globalLock);
- nwL = smb_allWaitingLocks;
- if (nwL == NULL) {
- osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
+ nwlRequest = smb_allWaitingLocks;
+ if (nwlRequest == NULL) {
+ osi_SleepW((LONG_PTR)&smb_allWaitingLocks, &smb_globalLock);
thrd_Sleep(1000);
continue;
+ } else {
+ first = 1;
+ osi_Log0(smb_logp, "smb_WaitingLocksDaemon starting wait lock check");
}
- else first = 1;
+
do {
if (first)
first = 0;
else
lock_ObtainWrite(&smb_globalLock);
- wL = nwL;
- nwL = (smb_waitingLock_t *) osi_QNext(&wL->q);
+
+ osi_Log1(smb_logp, " Checking waiting lock request %p", nwlRequest);
+
+ wlRequest = nwlRequest;
+ nwlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q);
lock_ReleaseWrite(&smb_globalLock);
- code = cm_RetryLock((cm_file_lock_t *) wL->lockp,
- wL->vcp->flags & SMB_VCFLAG_ALREADYDEAD);
+
+ code = 0;
+
+ for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
+ if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
+ continue;
+
+ osi_assert(wl->state != SMB_WAITINGLOCKSTATE_ERROR);
+
+ /* wl->state is either _DONE or _WAITING. _ERROR
+ would no longer be on the queue. */
+ code = cm_RetryLock( wl->lockp,
+ !!(wlRequest->vcp->flags & SMB_VCFLAG_ALREADYDEAD) );
+
+ if (code == 0) {
+ wl->state = SMB_WAITINGLOCKSTATE_DONE;
+ } else if (code != CM_ERROR_WOULDBLOCK) {
+ wl->state = SMB_WAITINGLOCKSTATE_ERROR;
+ break;
+ }
+ }
+
if (code == CM_ERROR_WOULDBLOCK) {
+
/* no progress */
- if (wL->timeRemaining != 0xffffffff
- && (wL->timeRemaining -= 1000) < 0)
+ if (wlRequest->timeRemaining != 0xffffffff
+ && (wlRequest->timeRemaining -= 1000) < 0)
goto endWait;
+
continue;
}
+
endWait:
- vcp = wL->vcp;
- inp = wL->inp;
- outp = wL->outp;
+
+ if (code != 0) {
+ cm_scache_t * scp;
+ cm_req_t req;
+
+ osi_Log1(smb_logp, "smb_WaitingLocksDaemon discarding lock req %p",
+ wlRequest);
+
+ scp = wlRequest->scp;
+
+ cm_InitReq(&req);
+
+ lock_ObtainMutex(&scp->mx);
+
+ for (wl = wlRequest->locks; wl; wl = wlNext) {
+ wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
+
+ cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
+ wl->LLength, wl->key, NULL, &req);
+
+ osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
+
+ free(wl);
+ }
+
+ lock_ReleaseMutex(&scp->mx);
+
+ } else {
+
+ osi_Log1(smb_logp, "smb_WaitingLocksDaemon granting lock req %p",
+ wlRequest);
+
+ for (wl = wlRequest->locks; wl; wl = wlNext) {
+ wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
+ osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
+ free(wl);
+ }
+ }
+
+ vcp = wlRequest->vcp;
+ inp = wlRequest->inp;
+ outp = wlRequest->outp;
ncbp = GetNCB();
ncbp->ncb_length = inp->ncb_length;
inp->spacep = cm_GetSpace();
/* Remove waitingLock from list */
lock_ObtainWrite(&smb_globalLock);
osi_QRemove((osi_queue_t **)&smb_allWaitingLocks,
- &wL->q);
+ &wlRequest->q);
lock_ReleaseWrite(&smb_globalLock);
/* Resume packet processing */
cm_FreeSpace(inp->spacep);
smb_FreePacket(inp);
smb_FreePacket(outp);
+ smb_ReleaseVC(vcp);
+ cm_ReleaseSCache(wlRequest->scp);
FreeNCB(ncbp);
- free(wL);
- } while (nwL);
+ free(wlRequest);
+ } while (nwlRequest && smbShutdownFlag == 0);
thrd_Sleep(1000);
}
}
return CM_ERROR_BADSMB;
strcpy(shareName, tp+1);
- userp = smb_GetUser(vcp, inp);
-
lock_ObtainMutex(&vcp->mx);
newTid = vcp->tidCounter++;
lock_ReleaseMutex(&vcp->mx);
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ userp = smb_GetUserFromUID(uidp);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
if (uidp)
smb_ReleaseUID(uidp);
long code = 0;
cm_scache_t *scp;
char *dptr;
- time_t dosTime;
+ afs_uint32 dosTime;
u_short shortTemp;
char attr;
smb_dirListPatch_t *patchp;
continue;
}
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
attr = smb_Attributes(scp);
/* check hidden attribute (the flag is only ON when dot file hiding is on ) */
if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
int returnedNames;
long nextEntryCookie;
int numDirChunks; /* # of 32 byte dir chunks in this entry */
- char resByte; /* reserved byte from the cookie */
+ char resByte; /* reserved byte from the cookie */
char *op; /* output data ptr */
- char *origOp; /* original value of op */
+ char *origOp; /* original value of op */
cm_space_t *spacep; /* for pathname buffer */
int starPattern;
int rootPath = 0;
memcpy(dsp->mask, mask, 11);
/* track if this is likely to match a lot of entries */
- if (smb_IsStarMask(mask)) starPattern = 1;
- else starPattern = 0;
- }
- else {
+ if (smb_IsStarMask(mask))
+ starPattern = 1;
+ else
+ starPattern = 0;
+ } else {
/* pull the next cookie value out of the search status block */
nextCookie = inCookiep[13] + (inCookiep[14]<<8) + (inCookiep[15]<<16)
+ (inCookiep[16]<<24);
dsp = smb_FindDirSearch(inCookiep[12]);
if (!dsp) {
/* can't find dir search status; fatal error */
+ osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%s]",
+ inCookiep[12], nextCookie, osi_LogSaveString(smb_logp, pathp));
return CM_ERROR_BADFD;
}
attribute = dsp->attribute;
starPattern = 1;
}
- osi_Log3(smb_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
+ osi_Log3(smb_logp, "SMB search dir cookie 0x%x, connection %d, attr 0x%x",
nextCookie, dsp->cookie, attribute);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* try to get the vnode for the path name next */
lock_ObtainMutex(&dsp->mx);
scp = dsp->scp;
cm_HoldSCache(scp);
code = 0;
- }
- else {
+ } else {
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, NULL, pathp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
smb_ReleaseDirSearch(dsp);
return CM_ERROR_NOFILES;
}
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
if (code == 0) {
- if (dsp->scp != 0)
- cm_ReleaseSCache(dsp->scp);
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ lock_ReleaseMutex(&dsp->mx);
+ cm_ReleaseUser(userp);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
dsp->scp = scp;
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done with this
&& LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
dsp->flags |= SMB_DIRSEARCH_BULKST;
+ dsp->scp->bulkStatProgress = hzero;
}
lock_ReleaseMutex(&scp->mx);
}
return code;
}
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
dirLength = scp->length;
bufferp = NULL;
bufferOffset.LowPart = bufferOffset.HighPart = 0;
/* check if we've returned all the names that will fit in the
* response packet.
*/
- if (returnedNames >= maxCount)
+ if (returnedNames >= maxCount) {
+ osi_Log2(smb_logp, "SMB search dir returnedNames %d >= maxCount %d",
+ returnedNames, maxCount);
break;
+ }
/* check if we've passed the dir's EOF */
if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) break;
* of the buffer we have. If not, get the buffer.
*/
thyper.HighPart = curOffset.HighPart;
- thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+ thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
LargeIntegerGreaterThanOrEqualTo(thyper,
scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
- int now = GetCurrentTime();
- if (now - req.startTime > 5000) {
+ int now = GetTickCount();
+ if (now - req.startTime > RDRtimeout) {
scp->bulkStatProgress = thyper;
scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
+ dsp->scp->bulkStatProgress = hzero;
} else
- cm_TryBulkStat(scp, &thyper, userp, &req);
+ code = cm_TryBulkStat(scp, &thyper, userp, &req);
}
} else {
lock_ObtainMutex(&scp->mx);
}
lock_ReleaseMutex(&dsp->mx);
- if (code)
+ if (code) {
+ osi_Log2(smb_logp, "SMB search dir buf_Get scp %x failed %d", scp, code);
break;
+ }
bufferOffset = thyper;
PRSFS_LOOKUP,
CM_SCACHESYNC_NEEDCALLBACK |
CM_SCACHESYNC_READ);
- if (code) break;
+ if (code) {
+ osi_Log2(smb_logp, "SMB search dir cm_SyncOp scp %x failed %d", scp, code);
+ break;
+ }
- if (cm_HaveBuffer(scp, bufferp, 0)) break;
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
+ if (cm_HaveBuffer(scp, bufferp, 0)) {
+ osi_Log2(smb_logp, "SMB search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+ break;
+ }
/* otherwise, load the buffer and try again */
code = cm_GetBuffer(scp, bufferp, NULL, userp, &req);
- if (code) break;
+ if (code) {
+ osi_Log3(smb_logp, "SMB search dir cm_GetBuffer failed scp %x bufferp %x code %d",
+ scp, bufferp, code);
+ break;
+ }
}
if (code) {
buf_Release(bufferp);
* it out if it represents a non-deleted entry.
*/
entryInDir = curOffset.LowPart & (2048-1);
- entryInBuffer = curOffset.LowPart & (buf_bufferSize - 1);
+ entryInBuffer = curOffset.LowPart & (cm_data.buf_blockSize - 1);
/* page header will help tell us which entries are free. Page header
* can change more often than once per buffer, since AFS 3 dir page size
* may be less than (but not more than a buffer package buffer.
*/
- temp = curOffset.LowPart & (buf_bufferSize - 1); /* only look intra-buffer */
+ temp = curOffset.LowPart & (cm_data.buf_blockSize - 1); /* only look intra-buffer */
temp &= ~(2048 - 1); /* turn off intra-page bits */
pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
actualName = shortName;
}
+ osi_Log3(smb_logp, "SMB search dir vn %d name %s (%s)",
+ dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+ osi_LogSaveString(smb_logp, actualName));
+
if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
/* this is one of the entries to use: it is not deleted
* and it matches the star pattern we're looking for.
* attributes */
/* no hidden files */
- if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName))
+ if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName)) {
+ osi_Log0(smb_logp, "SMB search dir skipping hidden");
goto nextEntry;
+ }
if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* no directories */
{
osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
"has filetype %d", osi_LogSaveString(smb_logp, dep->name),
fileType);
- if (fileType == CM_SCACHETYPE_DIRECTORY)
- goto nextEntry;
+ if (fileType == CM_SCACHETYPE_DIRECTORY ||
+ fileType == CM_SCACHETYPE_DFSLINK ||
+ fileType == CM_SCACHETYPE_INVALID)
+ osi_Log0(smb_logp, "SMB search dir skipping directory or bad link");
+ goto nextEntry;
}
*op++ = resByte;
memcpy(op, mask, 11); op += 11;
*op++ = (char) dsp->cookie; /* they say it must be non-zero */
- *op++ = nextEntryCookie & 0xff;
- *op++ = (nextEntryCookie>>8) & 0xff;
- *op++ = (nextEntryCookie>>16) & 0xff;
- *op++ = (nextEntryCookie>>24) & 0xff;
+ *op++ = (char)(nextEntryCookie & 0xff);
+ *op++ = (char)((nextEntryCookie>>8) & 0xff);
+ *op++ = (char)((nextEntryCookie>>16) & 0xff);
+ *op++ = (char)((nextEntryCookie>>24) & 0xff);
memcpy(op, &clientCookie, 4); op += 4;
/* now we emit the attribute. This is sort of tricky,
CharToOem(op, op);
/* Uppercase if requested by client */
- if ((((smb_t *)inp)->flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES) == 0)
+ if (!KNOWS_LONG_NAMES(inp))
_strupr(op);
op += 13;
/* release the mutex */
lock_ReleaseMutex(&scp->mx);
- if (bufferp) buf_Release(bufferp);
+ if (bufferp) {
+ buf_Release(bufferp);
+ bufferp = NULL;
+ }
/* 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.
*/
temp -= 3; /* deduct vbl block info */
osi_assert(temp == (43 * returnedNames));
- origOp[1] = temp & 0xff;
- origOp[2] = (temp>>8) & 0xff;
+ origOp[1] = (char)(temp & 0xff);
+ origOp[2] = (char)((temp>>8) & 0xff);
if (returnedNames == 0)
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
osi_Log1(smb_logp, "SMB receive check path %s",
osi_LogSaveString(smb_logp, pathp));
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if(code) {
+ if (code) {
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
cm_ReleaseUser(userp);
return code;
}
-
+
+#ifdef DFS_SUPPORT
+ if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(newScp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* now lock the vnode with a callback; returns with newScp locked */
lock_ObtainMutex(&newScp->mx);
code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
- if (code && code != CM_ERROR_NOACCESS) {
- lock_ReleaseMutex(&newScp->mx);
- cm_ReleaseSCache(newScp);
- cm_ReleaseUser(userp);
- return code;
+ if (code) {
+ if (code != CM_ERROR_NOACCESS) {
+ lock_ReleaseMutex(&newScp->mx);
+ cm_ReleaseSCache(newScp);
+ cm_ReleaseUser(userp);
+ return code;
+ }
+ } else {
+ cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
}
attrs = smb_Attributes(newScp);
- if (!(attrs & 0x10))
+ if (!(attrs & SMB_ATTR_DIRECTORY))
code = CM_ERROR_NOTDIR;
lock_ReleaseMutex(&newScp->mx);
unsigned short attribute;
cm_attr_t attr;
cm_scache_t *newScp;
- time_t dosTime;
+ afs_uint32 dosTime;
cm_user_t *userp;
int caseFold;
char *tidPathp;
osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
dosTime, attribute);
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return code;
}
-
+
+#ifdef DFS_SUPPORT
+ if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(newScp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* now lock the vnode with a callback; returns with newScp locked; we
* need the current status to determine what the new status is, in some
* cases.
return code;
}
+ cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
/* Check for RO volume */
if (newScp->flags & CM_SCACHEFLAG_RO) {
lock_ReleaseMutex(&newScp->mx);
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
smb_UnixTimeFromDosUTime(&attr.clientModTime, dosTime);
}
- if ((newScp->unixModeBits & 0222) && (attribute & 1) != 0) {
+ if ((newScp->unixModeBits & 0222) && (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 & 1) == 0) {
+ else if ((newScp->unixModeBits & 0222) == 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;
long code = 0;
cm_scache_t *rootScp;
cm_scache_t *newScp, *dscp;
- time_t dosTime;
+ afs_uint32 dosTime;
int attrs;
cm_user_t *userp;
int caseFold;
osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
osi_LogSaveString(smb_logp, pathp));
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* we shouldn't need this for V3 requests, but we seem to */
caseFold = CM_FLAG_CASEFOLD;
caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code == 0) {
- if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
- !dscp->mountRootFidp)
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ } else
+#endif /* DFS_SUPPORT */
+ if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
code = CM_ERROR_NOSUCHFILE;
else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
cm_buf_t *bp = buf_Find(dscp, &hzero);
- if (bp)
+ if (bp) {
buf_Release(bp);
- else
+ bp = NULL;
+ } else
code = CM_ERROR_NOSUCHFILE;
}
cm_ReleaseSCache(dscp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(newScp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* now lock the vnode with a callback; returns with newScp locked */
lock_ObtainMutex(&newScp->mx);
code = cm_SyncOp(newScp, NULL, userp, &req, 0,
return code;
}
+ 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_MOUNTPOINT ||
+ newScp->fileType == CM_SCACHETYPE_INVALID)
attrs = SMB_ATTR_DIRECTORY;
else
attrs = 0;
/* find the tree and free it */
tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
if (tidp) {
- lock_ObtainMutex(&tidp->mx);
- tidp->flags |= SMB_TIDFLAG_DELETE;
- lock_ReleaseMutex(&tidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
+ tidp->delete = 1;
+ lock_ReleaseWrite(&smb_rctLock);
smb_ReleaseTID(tidp);
}
long code = 0;
cm_user_t *userp;
cm_scache_t *scp;
- time_t dosTime;
+ afs_uint32 dosTime;
int caseFold;
cm_space_t *spacep;
char *tidPathp;
return 0;
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+ code = cm_NameI(cm_data.rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
tidPathp, &req, &scp);
if (code) {
return code;
}
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
code = cm_CheckOpen(scp, share & 0x7, 0, userp, &req);
if (code) {
cm_ReleaseSCache(scp);
/* save a pointer to the vnode */
fidp->scp = scp;
+ /* and the user */
+ cm_HoldUser(userp);
+ fidp->userp = userp;
+ lock_ObtainMutex(&fidp->mx);
if ((share & 0xf) == 0)
fidp->flags |= SMB_FID_OPENREAD;
else if ((share & 0xf) == 1)
fidp->flags |= SMB_FID_OPENWRITE;
else
fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
+ lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
smb_SetSMBParm(outp, 0, fidp->fid);
code = cm_Unlink(dscp, dep->name, rockp->userp, rockp->reqp);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
dscp, dep->name, NULL, TRUE);
if (code == 0) {
rockp->any = 1;
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
&req, &dscp);
-
if (code) {
cm_ReleaseUser(userp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. */
if (!lastNamep)
lastNamep = pathp;
DWORD filter;
cm_req_t req;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
cm_ReleaseUser(userp);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
- /*
- * Changed to use CASEFOLD always. This enables us to rename Foo/baz when
- * what actually exists is foo/baz. I don't know why the code used to be
- * the way it was. 1/29/96
- *
- * caseFold = ((vcp->flags & SMB_VCFLAG_USEV3) ? 0: CM_FLAG_CASEFOLD);
- *
- * Changed to use CM_FLAG_FOLLOW. 7/24/96
- *
- * caseFold = CM_FLAG_CASEFOLD;
- */
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
userp, tidPathp, &req, &oldDscp);
-
if (code) {
cm_ReleaseUser(userp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
cm_ReleaseUser(userp);
return code;
}
-
+
+#ifdef DFS_SUPPORT
+ if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseSCache(newDscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
+
/* otherwise, oldDscp and newDscp point to the corresponding directories.
* next, get the component names, and lower case them.
*/
else
code = CM_ERROR_EXISTS;
cm_ReleaseSCache(tmpscp2);
- tmpscp2 = NULL;
+ tmpscp2 = NULL;
} else {
code = CM_ERROR_NOSUCHFILE;
}
thyper.HighPart = 0;
code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
+ osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
if (code == CM_ERROR_STOPNOW)
code = 0;
DWORD filter;
cm_req_t req;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
userp, tidPathp, &req, &oldDscp);
if (code) {
cm_ReleaseUser(userp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
cm_ReleaseSCache(oldDscp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(newDscp);
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* Now, although we did two lookups for the two directories (because the same
* directory can be referenced through different paths), we only allow hard links
* within the same directory. */
/* now create the hardlink */
osi_Log1(smb_logp," Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep));
code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req);
- osi_Log1(smb_logp," Link returns %d", code);
+ osi_Log1(smb_logp," Link returns 0x%x", code);
/* Handle Change Notification */
if (code == 0) {
code = cm_RemoveDir(dscp, dep->name, rockp->userp, rockp->reqp);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
+ FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
dscp, dep->name, NULL, TRUE);
if (code == 0)
rockp->any = 1;
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. */
if (!lastNamep)
lastNamep = pathp;
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
- if (fidp)
- smb_ReleaseFID(fidp);
+ if (!fidp)
+ return CM_ERROR_BADFD;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
return CM_ERROR_BADFD;
}
+ lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_OPENWRITE)
- code = cm_FSync(fidp->scp, userp, &req);
- else
+ if (fidp->flags & SMB_FID_OPENWRITE) {
+ cm_scache_t * scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ cm_ReleaseSCache(scp);
+ } else {
code = 0;
- lock_ReleaseMutex(&fidp->mx);
+ lock_ReleaseMutex(&fidp->mx);
+ }
smb_ReleaseFID(fidp);
*newPathp = strdup(pathp);
}
-long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
-{
- unsigned short fid;
- smb_fid_t *fidp;
- cm_user_t *userp;
- long dosTime;
+long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
+ afs_uint32 dosTime) {
long code = 0;
cm_req_t req;
+ cm_scache_t *dscp = fidp->NTopen_dscp;
+ char *pathp = fidp->NTopen_pathp;
+ cm_scache_t * scp = fidp->scp;
+ int deleted = 0;
+ int nullcreator = 0;
+
+ osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
+ fidp, fidp->fid, vcp);
+
+ if (!userp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
+ lock_ReleaseMutex(&fidp->mx);
+ osi_Log0(smb_logp, " No user specified. Not closing fid");
+ return CM_ERROR_BADFD;
+ }
+
+ userp = fidp->userp; /* no hold required since fidp is held
+ throughout the function */
+ lock_ReleaseMutex(&fidp->mx);
+ }
cm_InitReq(&req);
- fid = smb_GetSMBParm(inp, 0);
- dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
-
- osi_Log1(smb_logp, "SMB close fid %d", fid);
-
- fid = smb_ChainFID(fid, inp);
- fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp) {
- return CM_ERROR_BADFD;
+ lock_ObtainWrite(&smb_rctLock);
+ if (fidp->delete) {
+ osi_Log0(smb_logp, " Fid already closed.");
+ lock_ReleaseWrite(&smb_rctLock);
+ return CM_ERROR_BADFD;
}
-
- userp = smb_GetUser(vcp, inp);
+ fidp->delete = 1;
+ lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
-
/* Don't jump the gun on an async raw write */
while (fidp->raw_writers) {
lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&fidp->mx);
}
- fidp->flags |= SMB_FID_DELETE;
-
/* watch for ioctl closes, and read-only opens */
- if (fidp->scp != NULL &&
+ if (scp != NULL &&
(fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
== SMB_FID_OPENWRITE) {
if (dosTime != 0 && dosTime != -1) {
- fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+ scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
/* This fixes defect 10958 */
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
}
- code = cm_FSync(fidp->scp, userp, &req);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ lock_ObtainMutex(&fidp->mx);
}
else
code = 0;
+ /* unlock any pending locks */
+ if (!(fidp->flags & SMB_FID_IOCTL) && scp &&
+ scp->fileType == CM_SCACHETYPE_FILE) {
+ cm_key_t key;
+ long tcode;
+
+ lock_ReleaseMutex(&fidp->mx);
+
+ /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
+ in zero. */
+ key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
+ lock_ObtainMutex(&scp->mx);
+
+ tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_GETSTATUS
+ | CM_SCACHESYNC_LOCK);
+
+ if (tcode) {
+ osi_Log1(smb_logp,
+ "smb CoreClose SyncOp failure code 0x%x", tcode);
+ goto post_syncopdone;
+ }
+
+ cm_UnlockByKey(scp, key, CM_UNLOCK_BY_FID, userp, &req);
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+
+ post_syncopdone:
+
+ lock_ReleaseMutex(&scp->mx);
+ lock_ObtainMutex(&fidp->mx);
+ }
+
if (fidp->flags & SMB_FID_DELONCLOSE) {
- cm_scache_t *dscp = fidp->NTopen_dscp;
- char *pathp = fidp->NTopen_pathp;
char *fullPathp;
- smb_FullName(dscp, fidp->scp, pathp, &fullPathp, userp, &req);
- if (fidp->scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_FullName(dscp, scp, pathp, &fullPathp, userp, &req);
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
code = cm_RemoveDir(dscp, fullPathp, userp, &req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- dscp, fullPathp, NULL, TRUE);
- }
- else
- {
+ if (code == 0) {
+ deleted = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ dscp, fullPathp, NULL, TRUE);
+ }
+ } else {
code = cm_Unlink(dscp, fullPathp, userp, &req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, fullPathp, NULL, TRUE);
+ if (code == 0) {
+ deleted = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ dscp, fullPathp, NULL, TRUE);
+ }
}
free(fullPathp);
+ lock_ObtainMutex(&fidp->mx);
+ fidp->flags &= ~SMB_FID_DELONCLOSE;
+ }
+
+ /* if this was a newly created file, then clear the creator
+ * in the stat cache entry. */
+ if (fidp->flags & SMB_FID_CREATED) {
+ nullcreator = 1;
+ fidp->flags &= ~SMB_FID_CREATED;
}
- lock_ReleaseMutex(&fidp->mx);
if (fidp->flags & SMB_FID_NTOPEN) {
- cm_ReleaseSCache(fidp->NTopen_dscp);
- free(fidp->NTopen_pathp);
+ fidp->NTopen_dscp = NULL;
+ fidp->NTopen_pathp = NULL;
+ fidp->flags &= ~SMB_FID_NTOPEN;
}
- if (fidp->NTopen_wholepathp)
+ if (fidp->NTopen_wholepathp) {
free(fidp->NTopen_wholepathp);
+ fidp->NTopen_wholepathp = NULL;
+ }
+ fidp->scp = NULL;
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+
+ if (scp) {
+ if (deleted || nullcreator) {
+ lock_ObtainMutex(&scp->mx);
+ if (nullcreator && scp->creator == userp)
+ scp->creator = NULL;
+ if (deleted)
+ scp->flags |= CM_SCACHEFLAG_DELETED;
+ lock_ReleaseMutex(&scp->mx);
+ }
+ cm_ReleaseSCache(scp);
+ }
+
+ if (pathp)
+ free(pathp);
+
+ return code;
+}
+
+long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+ unsigned short fid;
+ smb_fid_t *fidp;
+ cm_user_t *userp;
+ long code = 0;
+ afs_uint32 dosTime;
+
+ fid = smb_GetSMBParm(inp, 0);
+ dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
+
+ osi_Log1(smb_logp, "SMB ReceiveCoreClose fid %d", fid);
+
+ fid = smb_ChainFID(fid, inp);
+ fidp = smb_FindFID(vcp, fid, 0);
+ if (!fidp) {
+ return CM_ERROR_BADFD;
+ }
+
+ userp = smb_GetUserFromVCP(vcp, inp);
+
+ code = smb_CloseFID(vcp, fidp, userp, dosTime);
smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
/*
* smb_ReadData -- common code for Read, Read And X, and Raw Read
*/
-#ifndef DJGPP
long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
cm_user_t *userp, long *readp)
-#else /* DJGPP */
-long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
- cm_user_t *userp, long *readp, int dosflag)
-#endif /* !DJGPP */
{
osi_hyper_t offset;
long code = 0;
osi_hyper_t bufferOffset;
long bufIndex, nbytes;
int chunk;
- int sequential = 0;
+ int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
cm_req_t req;
cm_InitReq(&req);
fidp->prev_chunk = fidp->curr_chunk;
fidp->curr_chunk = chunk;
}
- if (fidp->curr_chunk == fidp->prev_chunk + 1)
+ if (!(fidp->flags & SMB_FID_RANDOM) && (fidp->curr_chunk == fidp->prev_chunk + 1))
sequential = 1;
- }
+ }
+ lock_ReleaseMutex(&fidp->mx);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) goto done;
+ if (code)
+ goto done;
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
/* now we have the entry locked, look up the length */
fileLength = scp->length;
/* otherwise, load up a buffer of data */
thyper.HighPart = offset.HighPart;
- thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
+ thyper.LowPart = offset.LowPart & ~(cm_data.buf_blockSize-1);
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
code = cm_SyncOp(scp, bufferp, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK |
CM_SCACHESYNC_READ);
- if (code) goto done;
-
+ if (code)
+ goto done;
+
+ cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
if (cm_HaveBuffer(scp, bufferp, 0)) break;
/* otherwise, load the buffer and try again */
/* now we have the right buffer loaded. Copy out the
* data from here to the user's buffer.
*/
- bufIndex = offset.LowPart & (buf_bufferSize - 1);
+ bufIndex = offset.LowPart & (cm_data.buf_blockSize - 1);
/* and figure out how many bytes we want from this buffer */
- nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */
+ nbytes = cm_data.buf_blockSize - bufIndex; /* what remains in buffer */
if (nbytes > count) nbytes = count; /* don't go past EOF */
/* now copy the data */
-#ifdef DJGPP
- if (dosflag)
- dosmemput(bufferp->datap + bufIndex, nbytes, (dos_ptr)op);
- else
-#endif /* DJGPP */
- memcpy(op, bufferp->datap + bufIndex, nbytes);
+ memcpy(op, bufferp->datap + bufIndex, nbytes);
/* adjust counters, pointers, etc. */
op += nbytes;
done:
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
- if (bufferp)
+ if (bufferp)
buf_Release(bufferp);
if (code == 0 && sequential)
/*
* smb_WriteData -- common code for Write and Raw Write
*/
-#ifndef DJGPP
long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
cm_user_t *userp, long *writtenp)
-#else /* DJGPP */
-long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
- cm_user_t *userp, long *writtenp, int dosflag)
-#endif /* !DJGPP */
{
osi_hyper_t offset;
long code = 0;
offset = *offsetp;
lock_ObtainMutex(&fidp->mx);
+ /* make sure we have a writable FD */
+ if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+ osi_Log2(smb_logp, "smb_WriteData fid %d not OPENWRITE flags 0x%x",
+ fidp->fid, fidp->flags);
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFDOP;
+ goto done;
+ }
+
scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainMutex(&scp->mx);
/* start by looking up the file's end */
- osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS",
- fidp->fid);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_SETSTATUS
| CM_SCACHESYNC_GETSTATUS);
- osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS returns %d",
- fidp->fid,code);
if (code)
goto done;
- /* make sure we have a writable FD */
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- code = CM_ERROR_BADFDOP;
- goto done;
- }
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);
/* now we have the entry locked, look up the length */
fileLength = scp->length;
/* handle over quota or out of space */
if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
*writtenp = written;
- code = CM_ERROR_QUOTA;
+ code = (scp->flags & CM_SCACHEFLAG_OVERQUOTA) ? CM_ERROR_QUOTA : CM_ERROR_SPACE;
break;
}
/* otherwise, load up a buffer of data */
thyper.HighPart = offset.HighPart;
- thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
+ thyper.LowPart = offset.LowPart & ~(cm_data.buf_blockSize-1);
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
/* now get the data in the cache */
while (1) {
- osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED",
- fidp->fid);
code = cm_SyncOp(scp, bufferp, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_WRITE
| CM_SCACHESYNC_BUFLOCKED);
- osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED returns %d",
- fidp->fid,code);
if (code)
goto done;
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+
/* If we're overwriting the entire buffer, or
* if we're writing at or past EOF, mark the
* buffer as current so we don't call
*/
if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength)
|| LargeIntegerEqualTo(offset, bufferp->offset)
- && (count >= buf_bufferSize
+ && (count >= cm_data.buf_blockSize
|| LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset,
ConvertLongToLargeInteger(count)),
minLength))) {
- if (count < buf_bufferSize
+ if (count < cm_data.buf_blockSize
&& bufferp->dataVersion == -1)
memset(bufferp->datap, 0,
- buf_bufferSize);
+ cm_data.buf_blockSize);
bufferp->dataVersion = scp->dataVersion;
}
/* now we have the right buffer loaded. Copy out the
* data from here to the user's buffer.
*/
- bufIndex = offset.LowPart & (buf_bufferSize - 1);
+ bufIndex = offset.LowPart & (cm_data.buf_blockSize - 1);
/* and figure out how many bytes we want from this buffer */
- nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */
+ nbytes = cm_data.buf_blockSize - bufIndex; /* what remains in buffer */
if (nbytes > count)
nbytes = count; /* don't go past end of request */
/* now copy the data */
-#ifdef DJGPP
- if (dosflag)
- dosmemget((dos_ptr)op, nbytes, bufferp->datap + bufIndex);
- else
-#endif /* DJGPP */
- memcpy(bufferp->datap + bufIndex, op, nbytes);
+ memcpy(bufferp->datap + bufIndex, op, nbytes);
buf_SetDirty(bufferp);
/* and record the last writer */
done:
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
+
if (bufferp) {
lock_ReleaseMutex(&bufferp->mx);
buf_Release(bufferp);
}
+ lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
&& (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
fidp->NTopen_dscp, fidp->NTopen_pathp,
NULL, TRUE);
}
+ lock_ReleaseMutex(&fidp->mx);
if (code == 0 && doWriteBack) {
long code2;
osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
fidp->fid);
code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
- osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns %d",
- fidp->fid,code2);
+ osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
+ fidp->fid, code2);
lock_ReleaseMutex(&scp->mx);
cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
writeBackOffset.HighPart, cm_chunkSize, 0, userp);
+ /* cm_SyncOpDone is called at the completion of cm_BkgStore */
}
- osi_Log3(smb_logp, "smb_WriteData fid %d returns %d written %d",
+ cm_ReleaseSCache(scp);
+
+ osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
fidp->fid, code, *writtenp);
return code;
}
long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- osi_hyper_t offset;
- long count, written = 0, total_written = 0;
unsigned short fd;
+ unsigned short count;
+ osi_hyper_t offset;
+ unsigned short hint;
+ long written = 0, total_written = 0;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp;
fd = smb_GetSMBParm(inp, 0);
count = smb_GetSMBParm(inp, 1);
offset.HighPart = 0; /* too bad */
- offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
+ offset.LowPart = smb_GetSMBParmLong(inp, 2);
+ hint = smb_GetSMBParm(inp, 4);
op = smb_GetSMBData(inp, NULL);
op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
+ osi_Log0(smb_logp, "smb_ReceiveCoreWrite fid not found");
return CM_ERROR_BADFD;
}
- if (fidp->flags & SMB_FID_IOCTL)
- return smb_IoctlWrite(fidp, vcp, inp, outp);
-
- userp = smb_GetUser(vcp, inp);
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_IoctlWrite(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ osi_Log1(smb_logp, "smb_ReceiveCoreWrite ioctl code 0x%x", code);
+ return code;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+ userp = smb_GetUserFromVCP(vcp, inp);
- /* special case: 0 bytes transferred means truncate to this position */
+ {
+ cm_key_t key;
+ LARGE_INTEGER LOffset;
+ LARGE_INTEGER LLength;
+
+ pid = ((smb_t *) inp)->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+ LOffset.HighPart = offset.HighPart;
+ LOffset.LowPart = offset.LowPart;
+ LLength.HighPart = 0;
+ LLength.LowPart = count;
+
+ lock_ObtainMutex(&fidp->scp->mx);
+ code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+ lock_ReleaseMutex(&fidp->scp->mx);
+
+ if (code) {
+ osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
+ goto done;
+ }
+ }
+
+ /* special case: 0 bytes transferred means truncate to this position */
if (count == 0) {
cm_req_t req;
+ osi_Log1(smb_logp, "smb_ReceiveCoreWrite truncation to length 0x%x", offset.LowPart);
+
cm_InitReq(&req);
truncAttr.mask = CM_ATTRMASK_LENGTH;
truncAttr.length.HighPart = 0;
lock_ObtainMutex(&fidp->mx);
code = cm_SetAttr(fidp->scp, &truncAttr, userp, &req);
+ fidp->flags |= SMB_FID_LENGTHSETDONE;
lock_ReleaseMutex(&fidp->mx);
- smb_SetSMBParm(outp, 0, /* count */ 0);
- smb_SetSMBDataLength(outp, 0);
- fidp->flags |= SMB_FID_LENGTHSETDONE;
- goto done;
+ smb_SetSMBParm(outp, 0, 0 /* count */);
+ smb_SetSMBDataLength(outp, 0);
+ goto done;
}
/*
* and don't set client mod time if we think that would go against the
* intention.
*/
+ lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
fidp->scp->clientModTime = time(NULL);
}
+ lock_ReleaseMutex(&fidp->mx);
code = 0;
while ( code == 0 && count > 0 ) {
-#ifndef DJGPP
code = smb_WriteData(fidp, &offset, count, op, userp, &written);
-#else /* DJGPP */
- code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
-#endif /* !DJGPP */
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
count -= written;
total_written += written;
written = 0;
}
+ osi_Log2(smb_logp, "smb_ReceiveCoreWrite total written 0x%x code 0x%x",
+ total_written, code);
+
/* set the packet data length to 3 bytes for the data block header,
* plus the size of the data.
*/
smb_SetSMBParm(outp, 0, total_written);
+ smb_SetSMBParmLong(outp, 1, offset.LowPart);
+ smb_SetSMBParm(outp, 3, hint);
smb_SetSMBDataLength(outp, 0);
done:
unsigned short fd;
smb_fid_t *fidp;
cm_user_t *userp;
-#ifndef DJGPP
char *rawBuf;
-#else /* DJGPP */
- dos_ptr rawBuf;
-#endif /* !DJGPP */
long written = 0;
long code = 0;
fd = smb_GetSMBParm(inp, 0);
fidp = smb_FindFID(vcp, fd, 0);
- osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
- rwcp->offset.LowPart, rwcp->count);
+ osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
+ rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
-#ifndef DJGPP
rawBuf = rwcp->buf;
code = smb_WriteData(fidp, &rwcp->offset, rwcp->count, rawBuf, userp,
&written);
-#else /* DJGPP */
- rawBuf = (dos_ptr) rwcp->buf;
- code = smb_WriteData(fidp, &rwcp->offset, rwcp->count,
- (unsigned char *) rawBuf, userp,
- &written, TRUE);
-#endif /* !DJGPP */
-
if (rwcp->writeMode & 0x1) { /* synchronous */
smb_t *op;
/* Give back raw buffer */
lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
*((char **)rawBuf) = smb_RawBufs;
-#else /* DJGPP */
- _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
smb_RawBufs = rawBuf;
lock_ReleaseMutex(&smb_RawBufLock);
cm_user_t *userp;
char *op;
unsigned short writeMode;
-#ifndef DJGPP
char *rawBuf;
-#else /* DJGPP */
- dos_ptr rawBuf;
-#endif /* !DJGPP */
-
fd = smb_GetSMBParm(inp, 0);
totalCount = smb_GetSMBParm(inp, 1);
count = smb_GetSMBParm(inp, 10);
- offset.HighPart = 0; /* too bad */
- offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
writeMode = smb_GetSMBParm(inp, 7);
op = (char *) inp->data;
op += smb_GetSMBParm(inp, 11);
+ offset.HighPart = 0;
+ offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+ if (*inp->wctp == 14) {
+ /* we received a 64-bit file offset */
+#ifdef AFS_LARGEFILES
+ offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+
+ if (LargeIntegerLessThanZero(offset)) {
+ osi_Log2(smb_logp,
+ "smb_ReceiveCoreWriteRaw received negative file offset 0x%x:%08x",
+ offset.HighPart, offset.LowPart);
+ return CM_ERROR_BADSMB;
+ }
+#else
+ if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+ osi_Log0(smb_logp,
+ "smb_ReceiveCoreWriteRaw received 64-bit file offset, but we don't support large files");
+ return CM_ERROR_BADSMB;
+ }
+
+ offset.HighPart = 0;
+#endif
+ } else {
+ offset.HighPart = 0; /* 32-bit file offset */
+ }
+
osi_Log4(smb_logp,
- "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
- fd, offset.LowPart, count, writeMode);
+ "smb_ReceiveCoreWriteRaw fd %d, off 0x%x:%08x, size 0x%x",
+ fd, offset.HighPart, offset.LowPart, count);
+ osi_Log1(smb_logp,
+ " WriteRaw WriteMode 0x%x",
+ writeMode);
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
return CM_ERROR_BADFD;
}
+
+ {
+ unsigned pid;
+ cm_key_t key;
+ LARGE_INTEGER LOffset;
+ LARGE_INTEGER LLength;
+
+ pid = ((smb_t *) inp)->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+ LOffset.HighPart = offset.HighPart;
+ LOffset.LowPart = offset.LowPart;
+ LLength.HighPart = 0;
+ LLength.LowPart = count;
+
+ lock_ObtainMutex(&fidp->scp->mx);
+ code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+ lock_ReleaseMutex(&fidp->scp->mx);
+
+ if (code) {
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+ }
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/*
* Work around bug in NT client
* and don't set client mod time if we think that would go against the
* intention.
*/
+ lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_LOOKSLIKECOPY) != SMB_FID_LOOKSLIKECOPY) {
fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
fidp->scp->clientModTime = time(NULL);
}
+ lock_ReleaseMutex(&fidp->mx);
code = 0;
while ( code == 0 && count > 0 ) {
-#ifndef DJGPP
code = smb_WriteData(fidp, &offset, count, op, userp, &written);
-#else /* DJGPP */
- code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
-#endif /* !DJGPP */
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
+
count -= written;
total_written += written;
written = 0;
if (smb_RawBufs) {
/* Get a raw buf, from head of list */
rawBuf = smb_RawBufs;
-#ifndef DJGPP
smb_RawBufs = *(char **)smb_RawBufs;
-#else /* DJGPP */
- smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
-#endif /* !DJGPP */
}
else
code = CM_ERROR_USESTD;
return code;
}
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(count));
+
rwcp->code = 0;
rwcp->buf = rawBuf;
- rwcp->offset.HighPart = 0;
- rwcp->offset.LowPart = offset.LowPart + count;
+ rwcp->offset.HighPart = offset.HighPart;
+ rwcp->offset.LowPart = offset.LowPart;
rwcp->count = totalCount - count;
rwcp->writeMode = writeMode;
rwcp->alreadyWritten = total_written;
osi_hyper_t offset;
long count, finalCount;
unsigned short fd;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp;
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp) {
+ if (!fidp)
return CM_ERROR_BADFD;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_IoctlRead(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
}
+ lock_ReleaseMutex(&fidp->mx);
+
+ {
+ LARGE_INTEGER LOffset, LLength;
+ cm_key_t key;
+
+ pid = ((smb_t *) inp)->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+ LOffset.HighPart = 0;
+ LOffset.LowPart = offset.LowPart;
+ LLength.HighPart = 0;
+ LLength.LowPart = count;
- if (fidp->flags & SMB_FID_IOCTL) {
- return smb_IoctlRead(fidp, vcp, inp, outp);
+ lock_ObtainMutex(&fidp->scp->mx);
+ code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+ lock_ReleaseMutex(&fidp->scp->mx);
+ }
+ if (code) {
+ smb_ReleaseFID(fidp);
+ return code;
}
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
/* remember this for final results */
smb_SetSMBParm(outp, 0, count);
*op++ = (unsigned char) (count & 0xff);
*op++ = (unsigned char) ((count >> 8) & 0xff);
-#ifndef DJGPP
code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
-#else /* DJGPP */
- code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
-#endif /* !DJGPP */
/* fix some things up */
smb_SetSMBParm(outp, 0, finalCount);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
userp, tidPathp, &req, &dscp);
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup, and
* fail if we find it. Otherwise, we do the create.
*/
int attributes;
char *lastNamep;
int caseFold;
- long dosTime;
+ afs_uint32 dosTime;
char *tidPathp;
cm_req_t req;
+ int created = 0; /* the file was new */
cm_InitReq(&req);
/* compute initial mode bits based on read-only flag in attributes */
initialModeBits = 0666;
- if (attributes & 1) initialModeBits &= ~0222;
+ if (attributes & SMB_ATTR_READONLY)
+ initialModeBits &= ~0222;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup, and
* truncate the file if we find it, otherwise we create the file.
*/
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (!excl && code == CM_ERROR_EXISTS) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assert(fidp);
- /* save a pointer to the vnode */
- fidp->scp = scp;
-
+ cm_HoldUser(userp);
+
+ lock_ObtainMutex(&fidp->mx);
/* always create it open for read/write */
fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
- smb_ReleaseFID(fidp);
-
+ /* remember that the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
+ /* save a pointer to the vnode */
+ fidp->scp = scp;
+ /* and the user */
+ fidp->userp = userp;
+ lock_ReleaseMutex(&fidp->mx);
+
smb_SetSMBParm(outp, 0, fidp->fid);
smb_SetSMBDataLength(outp, 0);
cm_Open(scp, 0, userp);
+ smb_ReleaseFID(fidp);
cm_ReleaseUser(userp);
/* leave scp held since we put it in fidp->scp */
return 0;
long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
+ osi_hyper_t new_offset;
long offset;
int whence;
unsigned short fd;
/* try to find the file descriptor */
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+
+ if (!fidp)
+ return CM_ERROR_BADFD;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
return CM_ERROR_BADFD;
}
+ lock_ReleaseMutex(&fidp->mx);
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code == 0) {
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (whence == 1) {
/* offset from current offset */
- offset += fidp->offset;
+ new_offset = LargeIntegerAdd(fidp->offset,
+ ConvertLongToLargeInteger(offset));
}
else if (whence == 2) {
/* offset from current EOF */
- offset += scp->length.LowPart;
+ new_offset = LargeIntegerAdd(scp->length,
+ ConvertLongToLargeInteger(offset));
+ } else {
+ new_offset = ConvertLongToLargeInteger(offset);
}
- fidp->offset = offset;
- smb_SetSMBParm(outp, 0, offset & 0xffff);
- smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
+
+ fidp->offset = new_offset;
+ smb_SetSMBParm(outp, 0, new_offset.LowPart & 0xffff);
+ smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
smb_SetSMBDataLength(outp, 0);
}
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
/* Sanity check */
if (ncbp->ncb_length < offsetof(struct smb, vdata)) {
/* log it and discard it */
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- char s[100];
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- sprintf(s, "SMB message too short, len %d", ncbp->ncb_length);
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL,
- 1, ncbp->ncb_length, ptbuf, inp);
- DeregisterEventSource(h);
-#else /* DJGPP */
- osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
-#endif /* !DJGPP */
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_TOO_SHORT,
+ __FILE__, __LINE__, ncbp->ncb_length);
+ osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
return;
}
/* Remember session generation number and time */
oldGen = sessionGen;
- oldTime = GetCurrentTime();
+ oldTime = GetTickCount();
while (inp->inCom != 0xff) {
dp = &smb_dispatchTable[inp->inCom];
if (inp->inCom == 0x1d)
/* Raw Write */
- code = smb_ReceiveCoreWriteRaw (vcp, inp, outp,
- rwcp);
+ code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
else {
- osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
- osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
code = (*(dp->procp)) (vcp, inp, outp);
- osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE);
- osi_Log1(smb_logp,"Dispatch return code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+ 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 )
}
if (oldGen != sessionGen) {
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- char s[100];
- newTime = GetCurrentTime();
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d",
- newTime - oldTime, ncbp->ncb_length);
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
- 1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
- DeregisterEventSource(h);
-#endif /* !DJGPP */
- osi_Log1(smb_logp, "Pkt straddled session startup, "
- "ncb length %d", ncbp->ncb_length);
+ newTime = GetTickCount();
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION,
+ newTime - oldTime, ncbp->ncb_length);
+ osi_Log2(smb_logp, "Pkt straddled session startup, "
+ "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
}
}
else {
smb_LogPacket(inp);
#endif /* LOG_PACKET */
-#ifndef DJGPP
if (showErrors) {
sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
if (code == IDCANCEL)
showErrors = 0;
}
-#endif /* DJGPP */
code = CM_ERROR_BADOP;
}
/* catastrophic failure: log as much as possible */
if (code == CM_ERROR_BADSMB) {
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- char s[100];
-
- osi_Log1(smb_logp,
- "Invalid SMB, ncb_length %d",
- ncbp->ncb_length);
-
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- sprintf(s, "Invalid SMB message, length %d",
- ncbp->ncb_length);
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
- 1, ncbp->ncb_length, ptbuf, smbp);
- DeregisterEventSource(h);
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_INVALID,
+ ncbp->ncb_length);
#ifdef LOG_PACKET
smb_LogPacket(inp);
#endif /* LOG_PACKET */
-#endif /* !DJGPP */
osi_Log1(smb_logp, "Invalid SMB message, length %d",
ncbp->ncb_length);
smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
- smbp->flg2 |= SMB_FLAGS2_ERR_STATUS;
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
break;
}
else {
/* tp now points to the new output record; go back and patch the
* second parameter (off2) to point to the new record.
*/
- temp = (unsigned int)tp - ((unsigned int) outp->data);
+ temp = (unsigned int)(tp - outp->data);
outWctp[3] = (unsigned char) (temp & 0xff);
outWctp[4] = (unsigned char) ((temp >> 8) & 0xff);
outWctp[2] = 0; /* padding */
outWctp = tp;
} /* while loop over all requests in the packet */
- /* done logging out, turn off logging-out flag */
- if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) {
- vcp->justLoggedOut = NULL;
- if (loggedOut) {
- loggedOut = 0;
- free(loggedOutName);
- loggedOutName = NULL;
- smb_ReleaseUID(loggedOutUserp);
- loggedOutUserp = NULL;
- }
- }
-
/* now send the output packet, and return */
if (!noSend)
smb_SendPacket(vcp, outp);
- thrd_Decrement(&ongoingOps);
-
- if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
- if (active_vcp) {
- smb_ReleaseVC(active_vcp);
- osi_Log2(smb_logp,
- "Replacing active_vcp %x with %x", active_vcp, vcp);
- }
- smb_HoldVC(vcp);
- active_vcp = vcp;
- last_msg_time = GetCurrentTime();
- }
- else if (active_vcp == vcp) {
- smb_ReleaseVC(active_vcp);
- active_vcp = NULL;
- }
+ thrd_Decrement(&ongoingOps);
return;
}
-#ifndef DJGPP
/* Wait for Netbios() calls to return, and make the results available to server
* threads. Note that server threads can't wait on the NCBevents array
* themselves, because NCB events are manual-reset, and the servers would race
DWORD code;
int idx;
- while (1) {
+ while (smbShutdownFlag == 0) {
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBevents,
FALSE, INFINITE);
- if (code == WAIT_OBJECT_0) {
- if (smbShutdownFlag == 1)
- break;
- else
- continue;
- }
+ if (code == WAIT_OBJECT_0)
+ continue;
/* error checking */
if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
thrd_SetEvent(NCBreturns[0][idx]);
}
}
-#endif /* !DJGPP */
/*
* Try to have one NCBRECV request waiting for every live session. Not more
DWORD code;
int idx_session, idx_NCB;
NCB *ncbp;
-#ifdef DJGPP
- dos_ptr dos_ncb;
-#endif /* DJGPP */
- while (1) {
+ while (smbShutdownFlag == 0) {
/* Get a session */
code = thrd_WaitForMultipleObjects_Event(numSessions, SessionEvents,
FALSE, INFINITE);
- if (code == WAIT_OBJECT_0) {
- if ( smbShutdownFlag == 1 )
- break;
- else
- continue;
- }
+ if (code == WAIT_OBJECT_0)
+ continue;
if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numSessions))
{
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBavails,
FALSE, INFINITE);
if (code == WAIT_OBJECT_0) {
- if ( smbShutdownFlag == 1 )
+ if (smbShutdownFlag == 1)
break;
else
goto NCBretry;
ncbp->ncb_lsn = (unsigned char) LSNs[idx_session];
ncbp->ncb_command = NCBRECV | ASYNCH;
ncbp->ncb_lana_num = lanas[idx_session];
-#ifndef DJGPP
ncbp->ncb_buffer = (unsigned char *) bufs[idx_NCB];
ncbp->ncb_event = NCBevents[idx_NCB];
ncbp->ncb_length = SMB_PACKETSIZE;
Netbios(ncbp);
-#else /* DJGPP */
- ncbp->ncb_buffer = bufs[idx_NCB]->dos_pkt;
- ((smb_ncb_t*)ncbp)->orig_pkt = bufs[idx_NCB];
- ncbp->ncb_event = NCBreturns[0][idx_NCB];
- ncbp->ncb_length = SMB_PACKETSIZE;
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
- Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
}
}
*/
void smb_Server(VOID *parmp)
{
- int myIdx = (int) parmp;
+ INT_PTR myIdx = (INT_PTR) parmp;
NCB *ncbp;
NCB *outncbp;
smb_packet_t *bufp;
UCHAR rc;
smb_vc_t *vcp = NULL;
smb_t *smbp;
-#ifdef DJGPP
- dos_ptr dos_ncb;
-#endif /* DJGPP */
+
+ rx_StartClientThread();
outncbp = GetNCB();
outbufp = GetPacket();
outbufp->ncbp = outncbp;
while (1) {
+ if (vcp) {
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
+ }
+
+ smb_ResetServerPriority();
+
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
FALSE, INFINITE);
if (idx_NCB < 0 || idx_NCB > (sizeof(NCBs) / sizeof(NCBs[0])))
{
/* this is fatal - log as much as possible */
- osi_Log1(smb_logp, "Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+ osi_Log1(smb_logp, "Fatal: idx_NCB %d out of range.\n", idx_NCB);
osi_assert(0);
}
ncbp = NCBs[idx_NCB];
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
idx_session = NCBsessions[idx_NCB];
rc = ncbp->ncb_retcode;
if (rc != NRC_PENDING && rc != NRC_GOODRET)
- osi_Log1(smb_logp, "NCBRECV failure code %d", rc);
+ osi_Log3(smb_logp, "NCBRECV failure lsn %d session %d: %s", ncbp->ncb_lsn, idx_session, ncb_error_string(rc));
switch (rc) {
- case NRC_GOODRET: break;
+ case NRC_GOODRET:
+ vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+ break;
case NRC_PENDING:
- /* Can this happen? Or is it just my
- * UNIX paranoia?
- */
+ /* Can this happen? Or is it just my UNIX paranoia? */
+ osi_Log2(smb_logp, "NCBRECV pending lsn %d session %d", ncbp->ncb_lsn, idx_session);
continue;
- case NRC_SCLOSED:
case NRC_SNUMOUT:
+ case NRC_SABORT:
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_UNEXPECTED_SMB_SESSION_CLOSE, ncb_error_string(rc));
+ /* fallthrough */
+ case NRC_SCLOSED:
/* Client closed session */
- if (reportSessionStartups)
- {
- osi_Log1(smb_logp, "session [ %d ] closed", idx_session);
- }
- dead_sessions[idx_session] = TRUE;
- if (vcp)
- smb_ReleaseVC(vcp);
vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
- /* Should also release vcp. [done] 2004-05-11 jaltman
- * Also, should do
- * sanity check that all TID's are gone.
- *
- * TODO: check if we could use LSNs[idx_session] instead,
- * also cleanup after dead vcp
- */
if (vcp) {
- if (dead_vcp)
- osi_Log1(smb_logp,
- "dead_vcp already set, %x",
- dead_vcp);
- if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
- osi_Log2(smb_logp,
- "setting dead_vcp %x, user struct %x",
+ lock_ObtainMutex(&vcp->mx);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
vcp, vcp->usersp);
- smb_HoldVC(vcp);
- dead_vcp = vcp;
vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- }
- if (vcp->justLoggedOut) {
- loggedOut = 1;
- loggedOutTime = vcp->logoffTime;
- loggedOutName = strdup(vcp->justLoggedOut->unp->name);
- loggedOutUserp = vcp->justLoggedOut;
- lock_ObtainWrite(&smb_rctLock);
- loggedOutUserp->refCount++;
- lock_ReleaseWrite(&smb_rctLock);
- }
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
}
goto doneWithNCB;
case NRC_INCOMP:
/* Treat as transient error */
- {
-#ifndef DJGPP
- EVENT_HANDLE h;
- char *ptbuf[1];
- char s[100];
-
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- sprintf(s, "SMB message incomplete, length %d",
- ncbp->ncb_length);
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
- 1001, NULL, 1,
- ncbp->ncb_length, ptbuf,
- bufp);
- DeregisterEventSource(h);
-#endif /* !DJGPP */
- osi_Log1(smb_logp,
- "dispatch smb recv failed, message incomplete, ncb_length %d",
- ncbp->ncb_length);
- osi_Log1(smb_logp,
- "SMB message incomplete, "
- "length %d", ncbp->ncb_length);
-
- /*
- * We used to discard the packet.
- * Instead, try handling it normally.
- *
- continue;
- */
- break;
- }
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_INCOMPLETE,
+ ncbp->ncb_length);
+ osi_Log1(smb_logp,
+ "dispatch smb recv failed, message incomplete, ncb_length %d",
+ ncbp->ncb_length);
+ osi_Log1(smb_logp,
+ "SMB message incomplete, "
+ "length %d", ncbp->ncb_length);
+
+ /*
+ * We used to discard the packet.
+ * Instead, try handling it normally.
+ *
+ continue;
+ */
+ vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+ break;
default:
- /* A weird error code. Log it, sleep, and
- * continue. */
+ /* A weird error code. Log it, sleep, and continue. */
+ vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+ if (vcp)
+ lock_ObtainMutex(&vcp->mx);
if (vcp && vcp->errorCount++ > 3) {
osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
- dead_sessions[idx_session] = TRUE;
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
+ goto doneWithNCB;
}
else {
+ if (vcp)
+ lock_ReleaseMutex(&vcp->mx);
thrd_Sleep(1000);
- thrd_SetEvent(SessionEvents[idx_session]);
+ thrd_SetEvent(SessionEvents[idx_session]);
}
- continue;
+ continue;
}
/* Success, so now dispatch on all the data in the packet */
if (smb_concurrentCalls > smb_maxObsConcurrentCalls)
smb_maxObsConcurrentCalls = smb_concurrentCalls;
- if (vcp)
- smb_ReleaseVC(vcp);
- vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
/*
* If at this point vcp is NULL (implies that packet was invalid)
* then we are in big trouble. This means either :
* a) we have the wrong NCB.
* b) Netbios screwed up the call.
+ * c) The VC was already marked dead before we were able to
+ * process the call
* Obviously this implies that
* ( LSNs[idx_session] != ncbp->ncb_lsn ||
* lanas[idx_session] != ncbp->ncb_lana_num )
* Log, sleep and resume.
*/
if (!vcp) {
- HANDLE h;
- char buf[1000];
- char *ptbuf[1];
-
- sprintf(buf,
- "Bad vcp!! : "
- "LSNs[idx_session]=[%d],"
- "lanas[idx_session]=[%d],"
- "ncbp->ncb_lsn=[%d],"
- "ncbp->ncb_lana_num=[%d]",
+ LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_VCP,
LSNs[idx_session],
lanas[idx_session],
ncbp->ncb_lsn,
ncbp->ncb_lana_num);
- ptbuf[0] = buf;
-
- h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
- if (h) {
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,sizeof(*ncbp),ptbuf,(void*)ncbp);
- DeregisterEventSource(h);
- }
-
/* Also log in the trace log. */
- osi_Log4(smb_logp, "Server: BAD VCP!"
+ osi_Log4(smb_logp, "Server: VCP does not exist!"
"LSNs[idx_session]=[%d],"
"lanas[idx_session]=[%d],"
"ncbp->ncb_lsn=[%d],"
continue;
}
+ smb_SetRequestStartTime();
vcp->errorCount = 0;
bufp = (struct smb_packet *) ncbp->ncb_buffer;
-#ifdef DJGPP
- bufp = ((smb_ncb_t *) ncbp)->orig_pkt;
- /* copy whole packet to virtual memory */
- /*fprintf(stderr, "smb_Server: copying dos packet at 0x%x, "
- "bufp=0x%x\n",
- bufp->dos_pkt / 16, bufp);*/
- fflush(stderr);
- dosmemget(bufp->dos_pkt, ncbp->ncb_length, bufp->data);
-#endif /* DJGPP */
smbp = (smb_t *)bufp->data;
outbufp->flags = 0;
-#if !defined(DJGPP) && !defined(AFS_WIN32_ENV)
__try
{
-#endif
if (smbp->com == 0x1d) {
/* Special handling for Write Raw */
raw_write_cont_t rwc;
ncbp->ncb_buffer = rwc.buf;
ncbp->ncb_length = 65535;
ncbp->ncb_event = rwevent;
-#ifndef DJGPP
Netbios(ncbp);
-#else
- Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
rcode = thrd_WaitForSingleObject_Event(rwevent, RAWTIMEOUT);
thrd_CloseHandle(rwevent);
}
/* TODO: what else needs to be serialized? */
smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
}
-#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
}
__except( smb_ServerExceptionFilter() ) {
}
-#endif
smb_concurrentCalls--;
-doneWithNCB:
+ doneWithNCB:
thrd_SetEvent(NCBavails[idx_NCB]);
}
if (vcp)
* force trace and give control to upstream exception handlers. Useful for
* debugging.
*/
-#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
DWORD smb_ServerExceptionFilter(void) {
/* While this is not the best time to do a trace, if it succeeds, then
* we have a trace (assuming tracing was enabled). Otherwise, this should
* throw a second exception.
*/
- HANDLE h;
- char *ptbuf[1];
-
- ptbuf[0] = "Unhandled exception forcing trace";
-
- h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
- if(h) {
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,0,ptbuf,NULL);
- DeregisterEventSource(h);
- }
-
+ LogEvent(EVENTLOG_ERROR_TYPE, MSG_UNHANDLED_EXCEPTION);
afsd_ForceTrace(TRUE);
buf_ForceTrace(TRUE);
return EXCEPTION_CONTINUE_SEARCH;
}
-#endif
/*
* Create a new NCB and associated events, packet buffer, and "space" buffer.
NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
-#ifndef DJGPP
sprintf(eventName,"NCBevents[%d]", idx);
NCBevents[idx] = thrd_CreateEvent(NULL, TRUE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
-#endif /* !DJGPP */
sprintf(eventName,"NCBReturns[0<=i<smb_NumServerThreads][%d]", idx);
retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
NCB *ncbp;
long code = 0;
long len;
- long i, j;
- smb_vc_t *vcp;
+ long i;
+ int session, thread;
+ smb_vc_t *vcp = NULL;
int flags = 0;
char rname[NCBNAMSZ+1];
char cname[MAX_COMPUTERNAME_LENGTH+1];
int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
-#ifdef DJGPP
- dos_ptr dos_ncb;
- time_t now;
-#endif /* DJGPP */
- int lana = (int) parmp;
+ INT_PTR lana = (INT_PTR) parmp;
ncbp = GetNCB();
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
/* retrieve computer name */
GetComputerName(cname, &cnamelen);
ncbp->ncb_sto = 0; /* No send timeout */
/* pad out with spaces instead of null termination */
- len = strlen(smb_localNamep);
+ len = (long)strlen(smb_localNamep);
strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
strcpy(ncbp->ncb_callname, "*");
for (i=1; i<NCBNAMSZ; i++) ncbp->ncb_callname[i] = ' ';
- ncbp->ncb_lana_num = lana;
+ ncbp->ncb_lana_num = (UCHAR)lana;
-#ifndef DJGPP
code = Netbios(ncbp);
-#else /* DJGPP */
- code = Netbios(ncbp, dos_ncb);
-#endif
if (code != 0)
{
-#ifndef DJGPP
char tbuffer[256];
-#endif
/* terminate silently if shutdown flag is set */
if (smbShutdownFlag == 1) {
-#ifndef DJGPP
ExitThread(1);
-#else
- thrd_Exit(1);
-#endif
}
osi_Log2(smb_logp,
osi_Log0(smb_logp,
"Client exiting due to network failure. Please restart client.\n");
-#ifndef DJGPP
sprintf(tbuffer,
"Client exiting due to network failure. Please restart client.\n"
"NCBLISTEN lana=%d failed with code %d",
if (showErrors)
code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
MB_OK|MB_SERVICE_NOTIFICATION);
- osi_assert(tbuffer);
- ExitThread(1);
-#else
- fprintf(stderr, "NCBLISTEN lana=%d failed with code %d\n",
- ncbp->ncb_lana_num, code);
- fprintf(stderr, "\nClient exiting due to network failure "
- "(possibly due to power-saving mode)\n");
- fprintf(stderr, "Please restart client.\n");
- afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
-#endif /* !DJGPP */
+ osi_panic(tbuffer, __FILE__, __LINE__);
}
/* check for remote conns */
if (strncmp(rname, cname, NCBNAMSZ) != 0)
flags |= SMB_VCFLAG_REMOTECONN;
- osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
/* lock */
lock_ObtainMutex(&smb_ListenerLock);
- /* New generation */
- sessionGen++;
-
- /* Log session startup */
-#ifdef NOTSERVICE
- fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host "
- "%s\n",
- ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
-#endif /* NOTSERVICE */
- osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
- ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
-
- if (reportSessionStartups) {
-#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
- char s[100];
-
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
- ptbuf[0] = s;
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
- 1, 0, ptbuf, NULL);
- DeregisterEventSource(h);
-#else /* DJGPP */
- time(&now);
- fprintf(stderr, "%s: New session %d starting from host %s\n",
- asctime(localtime(&now)), ncbp->ncb_lsn, rname);
- fflush(stderr);
-#endif /* !DJGPP */
- }
osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname));
- osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
- ongoingOps);
+ osi_Log1(smb_logp, "SMB session startup, %d ongoing ops", ongoingOps);
/* now ncbp->ncb_lsn is the connection ID */
vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
- vcp->flags |= flags;
- strcpy(vcp->rname, rname);
-
- /* Allocate slot in session arrays */
- /* Re-use dead session if possible, otherwise add one more */
- /* But don't look at session[0], it is reserved */
- for (i = 1; i < numSessions; i++) {
- if (dead_sessions[i]) {
- osi_Log1(smb_logp, "connecting to dead session [ %d ]", i);
- dead_sessions[i] = FALSE;
- break;
- }
- }
+ if (vcp->session == 0) {
+ /* New generation */
+ osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
+ sessionGen++;
- /* assert that we do not exceed the maximum number of sessions or NCBs.
- * we should probably want to wait for a session to be freed in case
- * we run out.
- */
+ /* Log session startup */
+#ifdef NOTSERVICE
+ fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
+ ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
+#endif /* NOTSERVICE */
+ osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
+ ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
+
+ if (reportSessionStartups) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, ongoingOps);
+ }
+
+ lock_ObtainMutex(&vcp->mx);
+ strcpy(vcp->rname, rname);
+ vcp->flags |= flags;
+ lock_ReleaseMutex(&vcp->mx);
+
+ /* Allocate slot in session arrays */
+ /* Re-use dead session if possible, otherwise add one more */
+ /* But don't look at session[0], it is reserved */
+ lock_ObtainWrite(&smb_globalLock);
+ for (session = 1; session < numSessions; session++) {
+ if (dead_sessions[session]) {
+ osi_Log1(smb_logp, "connecting to dead session [ %d ]", session);
+ dead_sessions[session] = FALSE;
+ break;
+ }
+ }
+ lock_ReleaseWrite(&smb_globalLock);
+ } else {
+ /* We are re-using an existing VC because the lsn and lana
+ * were re-used */
+ session = vcp->session;
+
+ osi_Log1(smb_logp, "Re-using session lsn %d", ncbp->ncb_lsn);
+
+ /* Log session startup */
+#ifdef NOTSERVICE
+ fprintf(stderr, "Re-using session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
+ ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
+#endif /* NOTSERVICE */
+ osi_Log4(smb_logp, "Re-using session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
+ ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
+
+ if (reportSessionStartups) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, ongoingOps);
+ }
+ }
+
+ if (session >= SESSION_MAX - 1 || numNCBs >= NCB_MAX - 1) {
+ unsigned long code = CM_ERROR_ALLBUSY;
+ smb_packet_t * outp = GetPacket();
+ unsigned char *outWctp;
+ smb_t *smbp;
+
+ smb_FormatResponsePacket(vcp, NULL, outp);
+ outp->ncbp = ncbp;
- osi_assert(i < Sessionmax - 1);
- osi_assert(numNCBs < NCBmax - 1); /* if we pass this test we can allocate one more */
+ if (vcp->flags & SMB_VCFLAG_STATUS32) {
+ unsigned long NTStatus;
+ smb_MapNTError(code, &NTStatus);
+ outWctp = outp->wctp;
+ smbp = (smb_t *) &outp->data;
+ *outWctp++ = 0;
+ *outWctp++ = 0;
+ *outWctp++ = 0;
+ smbp->rcls = (unsigned char) (NTStatus & 0xff);
+ smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+ smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+ smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+ } else {
+ unsigned short errCode;
+ unsigned char errClass;
+ smb_MapCoreError(code, vcp, &errCode, &errClass);
+ outWctp = outp->wctp;
+ smbp = (smb_t *) &outp->data;
+ *outWctp++ = 0;
+ *outWctp++ = 0;
+ *outWctp++ = 0;
+ smbp->errLow = (unsigned char) (errCode & 0xff);
+ smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+ smbp->rcls = errClass;
+ }
+ smb_SendPacket(vcp, outp);
+ smb_FreePacket(outp);
- LSNs[i] = ncbp->ncb_lsn;
- lanas[i] = ncbp->ncb_lana_num;
-
- if (i == numSessions) {
- /* Add new NCB for new session */
- char eventName[MAX_PATH];
-
- osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
-
- InitNCBslot(numNCBs);
- numNCBs++;
- thrd_SetEvent(NCBavails[0]);
- thrd_SetEvent(NCBevents[0]);
- for (j = 0; j < smb_NumServerThreads; j++)
- thrd_SetEvent(NCBreturns[j][0]);
- /* Also add new session event */
- sprintf(eventName, "SessionEvents[%d]", i);
- SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
- if ( GetLastError() == ERROR_ALREADY_EXISTS )
- osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
- numSessions++;
- osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
- thrd_SetEvent(SessionEvents[0]);
+ lock_ObtainMutex(&vcp->mx);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ smb_CleanupDeadVC(vcp);
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
} else {
- thrd_SetEvent(SessionEvents[i]);
+ /* assert that we do not exceed the maximum number of sessions or NCBs.
+ * we should probably want to wait for a session to be freed in case
+ * we run out.
+ */
+ osi_assert(session < SESSION_MAX - 1);
+ osi_assert(numNCBs < NCB_MAX - 1); /* if we pass this test we can allocate one more */
+
+ lock_ObtainMutex(&vcp->mx);
+ vcp->session = session;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ LSNs[session] = ncbp->ncb_lsn;
+ lanas[session] = ncbp->ncb_lana_num;
+ lock_ReleaseWrite(&smb_globalLock);
+
+ if (session == numSessions) {
+ /* Add new NCB for new session */
+ char eventName[MAX_PATH];
+
+ osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
+
+ InitNCBslot(numNCBs);
+ lock_ObtainWrite(&smb_globalLock);
+ numNCBs++;
+ lock_ReleaseWrite(&smb_globalLock);
+ thrd_SetEvent(NCBavails[0]);
+ thrd_SetEvent(NCBevents[0]);
+ for (thread = 0; thread < smb_NumServerThreads; thread++)
+ thrd_SetEvent(NCBreturns[thread][0]);
+ /* Also add new session event */
+ sprintf(eventName, "SessionEvents[%d]", session);
+ SessionEvents[session] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
+ lock_ObtainWrite(&smb_globalLock);
+ numSessions++;
+ lock_ReleaseWrite(&smb_globalLock);
+ osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
+ thrd_SetEvent(SessionEvents[0]);
+ } else {
+ thrd_SetEvent(SessionEvents[session]);
+ }
}
+ smb_ReleaseVC(vcp);
+
/* unlock */
lock_ReleaseMutex(&smb_ListenerLock);
-
} /* dispatch while loop */
}
void smb_NetbiosInit()
{
NCB *ncbp;
-#ifdef DJGPP
- dos_ptr dos_ncb;
-#endif /* DJGPP */
int i, lana, code, l;
char s[100];
int delname_tried=0;
int lana_found = 0;
OSVERSIONINFO Version;
- /* AFAIK, this is the default for the ms loopback adapter.*/
- unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
- /*******************************************************************/
-
/* Get the version of Windows */
memset(&Version, 0x00, sizeof(Version));
Version.dwOSVersionInfoSize = sizeof(Version);
/* setup the NCB system */
ncbp = GetNCB();
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
-#ifndef DJGPP
if (smb_LANadapter == -1) {
ncbp->ncb_command = NCBENUM;
ncbp->ncb_buffer = (PUCHAR)&lana_list;
ncbp->ncb_length = sizeof(lana_list);
code = Netbios(ncbp);
if (code != 0) {
- sprintf(s, "Netbios NCBENUM error code %d", code);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("Netbios NCBENUM error code %d", code);
osi_panic(s, __FILE__, __LINE__);
}
}
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- sprintf(s, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
lana_list.lana[i] = 255; /* invalid lana */
} else {
- sprintf(s, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
}
}
-#else
- /* for DJGPP, there is no NCBENUM and NCBRESET is a real reset. so
- we will just fake the LANA list */
- if (smb_LANadapter == -1) {
- for (i = 0; i < 8; i++)
- lana_list.lana[i] = i;
- lana_list.length = 8;
- }
- else {
- lana_list.length = 1;
- lana_list.lana[0] = smb_LANadapter;
- }
-#endif /* !DJGPP */
/* and declare our name so we can receive connections */
memset(ncbp, 0, sizeof(*ncbp));
len=lstrlen(smb_localNamep);
memset(smb_sharename,' ',NCBNAMSZ);
memcpy(smb_sharename,smb_localNamep,len);
- sprintf(s, "lana_list.length %d", lana_list.length);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("lana_list.length %d", lana_list.length);
/* Keep the name so we can unregister it later */
for (l = 0; l < lana_list.length; l++) {
ncbp->ncb_command = NCBADDNAME;
ncbp->ncb_lana_num = lana;
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
-#ifndef DJGPP
code = Netbios(ncbp);
-#else /* DJGPP */
- code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
- osi_Log4(smb_logp, "Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
+ afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
{
char name[NCBNAMSZ+1];
name[NCBNAMSZ]=0;
memcpy(name,ncbp->ncb_name,NCBNAMSZ);
- osi_Log1(smb_logp, "Netbios NCBADDNAME added new name >%s<",osi_LogSaveString(smb_logp, name));
+ afsi_log("Netbios NCBADDNAME added new name >%s<",name);
}
if (code == 0) code = ncbp->ncb_retcode;
if (code == 0) {
- osi_Log1(smb_logp, "Netbios NCBADDNAME succeeded on lana %d\n", lana);
-#ifdef DJGPP
- /* we only use one LANA with djgpp */
- lana_list.lana[0] = lana;
- lana_list.length = 1;
-#endif
+ afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
}
else {
- sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
if (code == NRC_BRIDGE) { /* invalid LANA num */
lana_list.lana[l] = 255;
continue;
}
else if (code == NRC_DUPNAME) {
- osi_Log0(smb_logp, "Name already exists; try to delete it");
+ afsi_log("Name already exists; try to delete it");
memset(ncbp, 0, sizeof(*ncbp));
ncbp->ncb_command = NCBDELNAME;
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
ncbp->ncb_lana_num = lana;
-#ifndef DJGPP
code = Netbios(ncbp);
-#else
- code = Netbios(ncbp, dos_ncb);
-#endif /* DJGPP */
if (code == 0)
code = ncbp->ncb_retcode;
else {
- sprintf(s, "Netbios NCBDELNAME lana %d error code %d\n", lana, code);
- osi_Log0(smb_logp, s);
+ afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code);
}
if (code != 0 || delname_tried) {
lana_list.lana[l] = 255;
}
}
else {
- sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
lana_list.lana[l] = 255; /* invalid lana */
osi_panic(s, __FILE__, __LINE__);
}
}
if (code == 0) {
lana_found = 1; /* at least one worked */
-#ifdef DJGPP
- break;
-#endif
}
}
osi_assert(lana_list.length >= 0);
if (!lana_found) {
- sprintf(s, "No valid LANA numbers found!");
- osi_panic(s, __FILE__, __LINE__);
+ osi_panic("No valid LANA numbers found!", __FILE__, __LINE__);
}
/* we're done with the NCB now */
void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
int nThreads
-#ifndef DJGPP
, void *aMBfunc
-#endif
)
{
thread_t phandle;
int lpid;
- int i;
+ INT_PTR i;
int len;
struct tm myTime;
-#ifdef DJGPP
- int npar, seg, sel;
- dos_ptr rawBuf;
-#endif /* DJGPP */
EVENT_HANDLE retHandle;
char eventName[MAX_PATH];
-#ifndef DJGPP
+ smb_TlsRequestSlot = TlsAlloc();
+
smb_MBfunc = aMBfunc;
-#endif /* DJGPP */
smb_useV3 = useV3;
smb_LANadapter = LANadapt;
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();
smb_logp = logp;
/* remember the name */
- len = strlen(snamep);
+ len = (int)strlen(snamep);
smb_localNamep = malloc(len+1);
strcpy(smb_localNamep, snamep);
afsi_log("smb_localNamep is >%s<", smb_localNamep);
lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
/* 4 Raw I/O buffers */
-#ifndef DJGPP
smb_RawBufs = calloc(65536,1);
*((char **)smb_RawBufs) = NULL;
for (i=0; i<3; i++) {
*((char **)rawBuf) = smb_RawBufs;
smb_RawBufs = rawBuf;
}
-#else /* DJGPP */
- npar = 65536 >> 4; /* number of paragraphs */
- seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[0]);
- if (seg == -1) {
- afsi_log("Cannot allocate %d paragraphs of DOS memory",
- npar);
- osi_panic("",__FILE__,__LINE__);
- }
- else {
- afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
- npar, seg);
- }
- smb_RawBufs = (seg * 16) + 0; /* DOS physical address */
-
- _farpokel(_dos_ds, smb_RawBufs, NULL);
- for (i=0; i<SMB_RAW_BUFS-1; i++) {
- npar = 65536 >> 4; /* number of paragraphs */
- seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[i+1]);
- if (seg == -1) {
- afsi_log("Cannot allocate %d paragraphs of DOS memory",
- npar);
- osi_panic("",__FILE__,__LINE__);
- }
- else {
- afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
- npar, seg);
- }
- rawBuf = (seg * 16) + 0; /* DOS physical address */
- /*_farpokel(_dos_ds, smb_RawBufs, smb_RawBufs);*/
- _farpokel(_dos_ds, rawBuf, smb_RawBufs);
- smb_RawBufs = rawBuf;
- }
-#endif /* !DJGPP */
/* global free lists */
smb_ncbFreeListp = NULL;
NCBevents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
afsi_log("Event Object Already Exists: %s", eventName);
- NCBreturns = malloc(nThreads * sizeof(EVENT_HANDLE *));
+ NCBreturns = malloc(smb_NumServerThreads * sizeof(EVENT_HANDLE *));
sprintf(eventName, "NCBreturns[0<=i<smb_NumServerThreads][0]");
retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
afsi_log("Event Object Already Exists: %s", eventName);
for (i = 0; i < smb_NumServerThreads; i++) {
- NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
+ NCBreturns[i] = malloc(NCB_MAX * sizeof(EVENT_HANDLE));
NCBreturns[i][0] = retHandle;
}
smb_ServerShutdown[i] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
afsi_log("Event Object Already Exists: %s", eventName);
+ InitNCBslot((int)(i+1));
}
-
- for (i = 1; i <= nThreads; i++)
- InitNCBslot(i);
- numNCBs = nThreads + 1;
+ numNCBs = smb_NumServerThreads + 1;
/* Initialize dispatch table */
memset(&smb_dispatchTable, 0, sizeof(smb_dispatchTable));
smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
+ smb_dispatchTable[0x2f].procp = smb_ReceiveV3WriteX;
+ smb_dispatchTable[0x2f].flags |= SMB_DISPATCHFLAG_CHAINED;
smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A; /* both are same */
smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
smb_tran2DispatchTable[13].procp = smb_ReceiveTran2CreateDirectory;
smb_tran2DispatchTable[14].procp = smb_ReceiveTran2SessionSetup;
+ smb_tran2DispatchTable[15].procp = smb_ReceiveTran2QFSInfoFid;
smb_tran2DispatchTable[16].procp = smb_ReceiveTran2GetDFSReferral;
smb_tran2DispatchTable[17].procp = smb_ReceiveTran2ReportDFSInconsistency;
/* if we are doing SMB authentication we have register outselves as a logon process */
if (smb_authType != SMB_AUTH_NONE) {
- NTSTATUS nts;
+ NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
LSA_STRING afsProcessName;
LSA_OPERATIONAL_MODE dummy; /*junk*/
afsProcessName.Buffer = "OpenAFSClientDaemon";
- afsProcessName.Length = strlen(afsProcessName.Buffer);
+ afsProcessName.Length = (USHORT)strlen(afsProcessName.Buffer);
afsProcessName.MaximumLength = afsProcessName.Length + 1;
nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy);
LSA_STRING packageName;
/* we are registered. Find out the security package id */
packageName.Buffer = MSV1_0_PACKAGE_NAME;
- packageName.Length = strlen(packageName.Buffer);
+ packageName.Length = (USHORT)strlen(packageName.Buffer);
packageName.MaximumLength = packageName.Length + 1;
nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage);
if (nts == STATUS_SUCCESS) {
+ /* BEGIN
+ * This code forces Windows to authenticate against the Logon Cache
+ * first instead of attempting to authenticate against the Domain
+ * Controller. When the Windows logon cache is enabled this improves
+ * performance by removing the network access and works around a bug
+ * seen at sites which are using a MIT Kerberos principal to login
+ * to machines joined to a non-root domain in a multi-domain forest.
+ */
+ PVOID pResponse = NULL;
+ ULONG cbResponse = 0;
+ MSV1_0_SETPROCESSOPTION_REQUEST OptionsRequest;
+
+ RtlZeroMemory(&OptionsRequest, sizeof(OptionsRequest));
+ OptionsRequest.MessageType = (MSV1_0_PROTOCOL_MESSAGE_TYPE) MsV1_0SetProcessOption;
+ OptionsRequest.ProcessOptions = MSV1_0_OPTION_TRY_CACHE_FIRST;
+ OptionsRequest.DisableOptions = FALSE;
+
+ nts = LsaCallAuthenticationPackage( smb_lsaHandle,
+ smb_lsaSecPackage,
+ &OptionsRequest,
+ sizeof(OptionsRequest),
+ &pResponse,
+ &cbResponse,
+ &ntsEx
+ );
+
+ if (nts != STATUS_SUCCESS && ntsEx != STATUS_SUCCESS) {
+ char message[256];
+ sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
+ nts, ntsEx);
+ OutputDebugString(message);
+ afsi_log(message);
+ } else {
+ OutputDebugString("MsV1_0SetProcessOption success");
+ afsi_log("MsV1_0SetProcessOption success");
+ }
+ /* END - code from Larry */
+
smb_lsaLogonOrigin.Buffer = "OpenAFS";
- smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer);
+ smb_lsaLogonOrigin.Length = (USHORT)strlen(smb_lsaLogonOrigin.Buffer);
smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1;
} else {
- afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts);
+ afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%lX]",nts);
+
+ /* something went wrong. We report the error and revert back to no authentication
+ because we can't perform any auth requests without a successful lsa handle
+ or sec package id. */
+ afsi_log("Reverting to NO SMB AUTH");
+ smb_authType = SMB_AUTH_NONE;
}
} else {
- afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts);
- }
+ afsi_log("Can't register logon process!! NTSTATUS=[%lX]",nts);
- if (nts != STATUS_SUCCESS) {
/* something went wrong. We report the error and revert back to no authentication
because we can't perform any auth requests without a successful lsa handle
or sec package id. */
afsi_log("Reverting to NO SMB AUTH");
smb_authType = SMB_AUTH_NONE;
- }
+ }
+
#ifdef COMMENT
/* Don't fallback to SMB_AUTH_NTLM. Apparently, allowing SPNEGO to be used each
* time prevents the failure of authentication when logged into Windows with an
/* Start listeners, waiters, servers, and daemons */
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == 255) continue;
+ if (lana_list.lana[i] == 255)
+ continue;
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
(void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
osi_assert(phandle != NULL);
thrd_CloseHandle(phandle);
}
-#ifndef DJGPP
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
NULL, 0, &lpid, "smb_ClientWaiter");
osi_assert(phandle != NULL);
thrd_CloseHandle(phandle);
-#endif /* !DJGPP */
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
NULL, 0, &lpid, "smb_ServerWaiter");
osi_assert(phandle != NULL);
thrd_CloseHandle(phandle);
- for (i=0; i<nThreads; i++) {
+ for (i=0; i<smb_NumServerThreads; i++) {
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Server,
(void *) i, 0, &lpid, "smb_Server");
osi_assert(phandle != NULL);
osi_assert(phandle != NULL);
thrd_CloseHandle(phandle);
-#ifdef DJGPP
- smb_ListShares();
-#endif
-
return;
}
void smb_Shutdown(void)
{
NCB *ncbp;
-#ifdef DJGPP
- dos_ptr dos_ncb;
-#endif
long code = 0;
int i;
+ smb_vc_t *vcp;
/*fprintf(stderr, "Entering smb_Shutdown\n");*/
/* setup the NCB system */
ncbp = GetNCB();
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif
/* Block new sessions by setting shutdown flag */
smbShutdownFlag = 1;
/*fprintf(stderr, "NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
ncbp->ncb_command = NCBHANGUP;
ncbp->ncb_lana_num = lanas[i]; /*smb_LANadapter;*/
- ncbp->ncb_lsn = LSNs[i];
-#ifndef DJGPP
+ ncbp->ncb_lsn = (UCHAR)LSNs[i];
code = Netbios(ncbp);
-#else
- code = Netbios(ncbp, dos_ncb);
-#endif
/*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
if (code == 0) code = ncbp->ncb_retcode;
if (code != 0) {
}
}
+ /* Trigger the shutdown of all SMB threads */
+ for (i = 0; i < smb_NumServerThreads; i++)
+ thrd_SetEvent(NCBreturns[i][0]);
+
+ thrd_SetEvent(NCBevents[0]);
+ thrd_SetEvent(SessionEvents[0]);
+ thrd_SetEvent(NCBavails[0]);
+
+ for (i = 0;i < smb_NumServerThreads; i++) {
+ DWORD code = thrd_WaitForSingleObject_Event(smb_ServerShutdown[i], 500);
+ if (code == WAIT_OBJECT_0) {
+ continue;
+ } else {
+ afsi_log("smb_Shutdown thread [%d] did not stop; retry ...",i);
+ thrd_SetEvent(NCBreturns[i--][0]);
+ }
+ }
+
/* Delete Netbios name */
memset((char *)ncbp, 0, sizeof(NCB));
for (i = 0; i < lana_list.length; i++) {
ncbp->ncb_command = NCBDELNAME;
ncbp->ncb_lana_num = lana_list.lana[i];
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
-#ifndef DJGPP
code = Netbios(ncbp);
-#else
- code = Netbios(ncbp, dos_ncb);
-#endif
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
fflush(stderr);
}
- /* Trigger the shutdown of all SMB threads */
- for (i = 0; i < smb_NumServerThreads; i++)
- thrd_SetEvent(NCBreturns[i][0]);
+ /* Release the reference counts held by the VCs */
+ lock_ObtainWrite(&smb_rctLock);
+ for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
+ {
+ smb_fid_t *fidp;
+ smb_tid_t *tidp;
+
+ if (vcp->magic != SMB_VC_MAGIC)
+ osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
+ __FILE__, __LINE__);
- thrd_SetEvent(NCBevents[0]);
- thrd_SetEvent(SessionEvents[0]);
- thrd_SetEvent(NCBavails[0]);
+ for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+ {
+ if (fidp->scp != NULL) {
+ cm_scache_t * scp;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->scp != NULL) {
+ scp = fidp->scp;
+ fidp->scp = NULL;
+ cm_ReleaseSCache(scp);
+ }
+ lock_ReleaseMutex(&fidp->mx);
+ }
+ }
- for (i = 0;i < smb_NumServerThreads; i++) {
- DWORD code = thrd_WaitForSingleObject_Event(smb_ServerShutdown[i], INFINITE);
- if (code == WAIT_OBJECT_0) {
- continue;
- } else {
- afsi_log("smb_Shutdown[%d] wait error",i);
+ for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ if (tidp->vcp)
+ smb_ReleaseVCNoLock(tidp->vcp);
+ if (tidp->userp) {
+ cm_user_t *userp = tidp->userp;
+ tidp->userp = NULL;
+ lock_ReleaseWrite(&smb_rctLock);
+ cm_ReleaseUser(userp);
+ lock_ObtainWrite(&smb_rctLock);
+ }
}
}
+ lock_ReleaseWrite(&smb_rctLock);
+
+ TlsFree(smb_TlsRequestSlot);
}
/* Get the UNC \\<servername>\<sharename> prefix. */
*cp = 0;
- osi_Log0( smb_logp, osi_LogSaveString(smb_logp, buf));
+ osi_Log1( smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
}
osi_Log0(smb_logp, "*** End SMB packet dump ***");
#endif /* LOG_PACKET */
-int smb_DumpVCP(FILE *outputFile, char *cookie)
+int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
{
int zilch;
char output[1024];
smb_vc_t *vcp;
- lock_ObtainRead(&smb_rctLock);
+ if (lock)
+ lock_ObtainRead(&smb_rctLock);
+
+ sprintf(output, "begin dumping smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
+ {
+ smb_fid_t *fidp;
+
+ sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\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\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\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
+ fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL",
+ fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping smb_fid_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, "begin dumping DEAD smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp)
+ {
+ smb_fid_t *fidp;
+
+ sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\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\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\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
+ fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL",
+ fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping smb_fid_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping DEAD smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping vcpsp\n");
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ sprintf(output, "begin dumping DEAD smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
+ for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
- sprintf(output, "%s vcp=0x%08X, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+ sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping fidsp\n");
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ sprintf(output, "begin dumping smb_fid_t\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 -- fidp=0x%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, NTopen_pathp=%s, NTopen_wholepathp=%s\n",
+ 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\n",
cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL",
fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping fidsp\n");
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ sprintf(output, "done dumping smb_fid_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping vcpsp\n");
- WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+ sprintf(output, "done dumping DEAD smb_vc_t\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- lock_ReleaseRead(&smb_rctLock);
+ if (lock)
+ lock_ReleaseRead(&smb_rctLock);
return 0;
}