* 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>
+#include <ntstatus.h>
#else
#include <sys/timeb.h>
#include <tzfile.h>
#include <time.h>
#include <osi.h>
-#include <ntstatus.h>
+#include <rx\rx.h>
+#include <rx/rx_prototypes.h>
#include "afsd.h"
+#include <WINNT\afsreg.h>
#include "smb.h"
#include "lanahelper.h"
int smb_LogoffTokenTransfer;
time_t smb_LogoffTransferTimeout;
+int smb_StoreAnsiFilenames = 0;
+
DWORD last_msg_time = 0;
long ongoingOps = 0;
#define NCBmax MAXIMUM_WAIT_OBJECTS
EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
EVENT_HANDLE **NCBreturns;
+EVENT_HANDLE **NCBShutdown;
+EVENT_HANDLE *smb_ServerShutdown;
DWORD NCBsessions[NCBmax];
NCB *NCBs[NCBmax];
struct smb_packet *bufs[NCBmax];
static showErrors = 1;
/* 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.
* When added to dosUTime, gives Unix (AFS) time.
*/
-long smb_localZero = 0;
+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_username_t *usernamesp = NULL;
-smb_waitingLock_t *smb_allWaitingLocks;
+smb_waitingLockRequest_t *smb_allWaitingLocks;
/* forward decl */
void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
#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;
return "S(0d)_ReceiveTran2CreateDirectory";
case 14:
return "S(0e)_ReceiveTran2SessionSetup";
+ case 16:
+ return "S(10)_ReceiveTran2GetDfsReferral";
+ case 17:
+ return "S(11)_ReceiveTran2ReportDfsInconsistency";
}
}
{
unsigned int attrs;
- if (scp->fileType == CM_SCACHETYPE_DIRECTORY
- || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID)
+ {
attrs = SMB_ATTR_DIRECTORY;
- else
+#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;
}
#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 */
#ifndef DJGPP
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+{
+ // Note that LONGLONG is a 64-bit value
+ LONGLONG ll;
+
+ ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
+ largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
+ largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
+}
+#else
void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
{
struct tm *ltp;
SystemTimeToFileTime(&stm, largeTimep);
}
+#endif /* USE_NUMERIC_TIME_CONV */
#else /* DJGPP */
void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
{
#endif /* !DJGPP */
#ifndef DJGPP
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
+{
+ // Note that LONGLONG is a 64-bit value
+ LONGLONG ll;
+
+ 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;
}
+#endif /* USE_NUMERIC_TIME_CONV */
#else /* DJGPP */
void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
{
}
#endif /* !DJGPP */
-void smb_SearchTimeFromUnixTime(long *dosTimep, time_t unixTime)
+void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
{
struct tm *ltp;
int dosDate;
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;
struct tm localTm;
- dosDate = searchTime & 0xffff;
- dosTime = (searchTime >> 16) & 0xffff;
+ dosDate = (unsigned short) (searchTime & 0xffff);
+ dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
*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;
}
-void smb_UnixTimeFromDosUTime(time_t *unixTimep, time_t dosTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
{
#ifndef DJGPP
*unixTimep = dosTime + smb_localZero;
smb_vc_t *vcp;
lock_ObtainWrite(&smb_rctLock);
- for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
+ for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
if (lsn == vcp->lsn && lana == vcp->lana) {
- vcp->refCount++;
+ smb_HoldVCNoLock(vcp);
break;
}
}
/* 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) {
+ numVCs = 0;
+ osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
+ }
}
lock_ReleaseWrite(&smb_rctLock);
return vcp;
return 0;
}
+void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+{
+ osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+#ifdef DEBUG
+ osi_assert(vcp->refCount-- != 0);
+#else
+ vcp->refCount--;
+#endif
+}
+
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);
+#ifdef DEBUG
+ osi_assert(vcp->refCount-- != 0);
+#else
+ vcp->refCount--;
+#endif
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);
}
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;
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)) {
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 = 0;
}
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)
uidp->nextp = vcp->usersp;
uidp->refCount = 1;
uidp->vcp = vcp;
- vcp->refCount++;
+ smb_HoldVCNoLock(vcp);
vcp->usersp = uidp;
lock_InitializeMutex(&uidp->mx, "user_t mutex");
uidp->userID = uid;
smb_user_t *up;
smb_user_t **lupp;
cm_user_t *userp;
- smb_vc_t *vcp;
userp = NULL;
- vcp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(uidp->refCount-- > 0);
if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
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;
+ userp = uidp->unp->userp; /* avoid deadlock by releasing */
+ uidp->unp->userp = NULL; /* after releasing the lock */
}
- vcp = uidp->vcp;
+ smb_ReleaseVCNoLock(uidp->vcp);
uidp->vcp = NULL;
}
lock_ReleaseWrite(&smb_rctLock);
cm_ReleaseUserVCRef(userp);
cm_ReleaseUser(userp);
}
- if (vcp) {
- smb_ReleaseVC(vcp);
- }
}
+
/* retrieve a held reference to a user structure corresponding to an incoming
* request.
* corresponding release function is cm_ReleaseUser.
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.
*/
break;
}
}
+
if (!fidp && (flags & SMB_FLAG_CREATE)) {
char eventName[MAX_PATH];
EVENT_HANDLE event;
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;
vcp->fidCounter = 1;
}
}
+
lock_ReleaseWrite(&smb_rctLock);
return fidp;
}
osi_assert(fidp->refCount-- > 0);
if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
vcp = fidp->vcp;
- if (!(fidp->flags & SMB_FID_IOCTL))
- scp = fidp->scp;
+ fidp->vcp = 0;
+ scp = fidp->scp; /* release after lock is released */
+ fidp->scp = 0;
+
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);
}
free(fidp);
- /* do not call smb_ReleaseVC() because we already have the lock */
- vcp->refCount--;
+ smb_ReleaseVCNoLock(vcp);
}
lock_ReleaseWrite(&smb_rctLock);
{
int matchType = 0;
smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
- if(!strnicmp(dep->name, vrock->shareName, 12)) {
+ if (!strnicmp(dep->name, vrock->shareName, 12)) {
if(!stricmp(dep->name, vrock->shareName))
matchType = SMB_FINDSHARE_EXACT_MATCH;
else
* 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);
}
#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);
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) {
+ if (vrock.matchType) {
sprintf(pathName,"/%s/",vrock.match);
*pathNamep = strdup(strlwr(pathName));
free(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,
/* find a dir search structure by cookie value, and return it held.
* Must be called with smb_globalLock held.
*/
-smb_dirSearch_t *smb_FindDirSearchNL(long cookie)
+smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
{
smb_dirSearch_t *dsp;
- for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
+ for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
if (dsp->cookie == cookie) {
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)
smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
}
+ lock_ObtainMutex(&dsp->mx);
dsp->refCount++;
+ lock_ReleaseMutex(&dsp->mx);
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;
}
void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
{
lock_ObtainWrite(&smb_globalLock);
- dsp->flags |= SMB_DIRSEARCH_DELETE;
- lock_ReleaseWrite(&smb_globalLock);
lock_ObtainMutex(&dsp->mx);
- if(dsp->scp != NULL) {
+ dsp->flags |= SMB_DIRSEARCH_DELETE;
+ if (dsp->scp != NULL) {
lock_ObtainMutex(&dsp->scp->mx);
if (dsp->flags & SMB_DIRSEARCH_BULKST) {
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
lock_ReleaseMutex(&dsp->scp->mx);
}
lock_ReleaseMutex(&dsp->mx);
+ lock_ReleaseWrite(&smb_globalLock);
}
-void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
+/* 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_ObtainWrite(&smb_globalLock);
+ lock_ObtainMutex(&dsp->mx);
osi_assert(dsp->refCount-- > 0);
if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ lock_ReleaseMutex(&dsp->mx);
lock_FinalizeMutex(&dsp->mx);
scp = dsp->scp;
free(dsp);
+ } else {
+ lock_ReleaseMutex(&dsp->mx);
}
- lock_ReleaseWrite(&smb_globalLock);
-
/* 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)
+{
+ lock_ObtainWrite(&smb_globalLock);
+ smb_ReleaseDirSearchNoLock(dsp);
+ lock_ReleaseWrite(&smb_globalLock);
}
/* find a dir search structure by cookie value, and return it held */
smb_dirSearch_t *dsp;
lock_ObtainWrite(&smb_globalLock);
- dsp = smb_FindDirSearchNL(cookie);
+ dsp = smb_FindDirSearchNoLock(cookie);
lock_ReleaseWrite(&smb_globalLock);
return dsp;
}
int i;
victimCount = 0; /* how many have we got so far */
- for(tp = smb_lastDirSearchp; tp; tp=prevp) {
+ for (tp = smb_lastDirSearchp; tp; tp=prevp) {
/* we'll move tp from queue, so
* do this early.
*/
}
/* don't do more than this */
- if (victimCount >= SMB_DIRSEARCH_GCMAX) break;
+ if (victimCount >= SMB_DIRSEARCH_GCMAX)
+ break;
}
/* now release them */
- lock_ReleaseWrite(&smb_globalLock);
- for(i = 0; i < victimCount; i++) {
- smb_ReleaseDirSearch(victimsp[i]);
+ for (i = 0; i < victimCount; i++) {
+ smb_ReleaseDirSearchNoLock(victimsp[i]);
}
- lock_ObtainWrite(&smb_globalLock);
}
/* function for allocating a dir search entry. We need these to remember enough context
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 */
- if (isV3) maxAllowed = 65535;
- else maxAllowed = 255;
+ maxAllowed = isV3 ? 65535 : 255;
+ if (smb_dirSearchCounter > maxAllowed)
+ smb_dirSearchCounter = 1;
+
+ start = smb_dirSearchCounter;
- while(1) {
+ while (1) {
/* twice so we have enough tries to find guys we GC after one pass;
* 10 extra is just in case I mis-counted.
*/
- if (++counter > 2*maxAllowed+10) osi_panic("afsd: dir search cookie leak",
- __FILE__, __LINE__);
+ if (++counter > 2*maxAllowed+10)
+ osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
+
if (smb_dirSearchCounter > maxAllowed) {
smb_dirSearchCounter = 1;
- smb_GCDirSearches(isV3); /* GC some (drops global lock) */
- }
- dsp = smb_FindDirSearchNL(smb_dirSearchCounter);
+ }
+ 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
* we haven't dropped the global lock.
*/
+ lock_ObtainMutex(&dsp->mx);
dsp->refCount--;
+ lock_ReleaseMutex(&dsp->mx);
++smb_dirSearchCounter;
continue;
}
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);
tbp = GetPacket();
memcpy(tbp, pkt, sizeof(smb_packet_t));
tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
+ if (tbp->vcp)
+ smb_HoldVC(tbp->vcp);
return tbp;
}
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)
1, smbp->ncb_length, ptbuf, smbp);
DeregisterEventSource(h);
#endif
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
+ parm, parmCount, smbp->ncb_length);
osi_panic(s, __FILE__, __LINE__);
}
parmDatap = smbp->wctp + (2*parm) + 1;
1, smbp->ncb_length, ptbuf, smbp);
DeregisterEventSource(h);
#endif
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+ 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;
outp->res[1] = inSmbp->res[1];
op->inCom = inSmbp->com;
}
- outp->reb = 0x80; /* SERVER_RESP */
- outp->flg2 = 0x1; /* KNOWS_LONG_NAMES */
+ outp->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
+ outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
/* copy fields in generic packet area */
op->wctp = &outp->wct;
code = Netbios(ncbp, dos_ncb);
#endif /* !DJGPP */
- if (code != 0)
- osi_Log1(smb_logp, "SendPacket failure code %d", code);
+ if (code != 0) {
+ 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";
+ }
+ osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
+ }
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 */
}
else if (code == CM_ERROR_GSSCONTINUE) {
NTStatus = 0xC0000016L; /* more processing required */
}
+ else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
+#ifdef COMMENT
+ NTStatus = 0xC0000280L; /* reparse point not resolved */
+#else
+ NTStatus = 0xC0000022L; /* Access Denied */
+#endif
+ }
+ 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) {
+ 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) {
+ NTStatus = 0xC00000BEL; /* Bad Network Path */
+ }
+#endif
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;
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 = 0;
+ 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 */
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",
* 32-bit error codes *
* and NT Find *
* and NT SMB's *
- * and raw mode */
+ * and raw mode
+ * and DFS */
caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
+#ifdef DFS_SUPPORT
+ NTNEGOTIATE_CAPABILITY_DFS |
+#endif
NTNEGOTIATE_CAPABILITY_NTFIND |
NTNEGOTIATE_CAPABILITY_RAWMODE |
NTNEGOTIATE_CAPABILITY_NTSMB;
{
afs_uint32 count = 0;
- while(1) {
+ while(smbShutdownFlag == 0) {
count++;
thrd_Sleep(10000);
+
+ if (smbShutdownFlag == 1)
+ break;
+
if ((count % 72) == 0) { /* every five minutes */
struct tm myTime;
- long old_localZero = smb_localZero;
+ time_t old_localZero = smb_localZero;
/* Initialize smb_localZero */
myTime.tm_isdst = -1; /* compute whether on DST or not */
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();
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) {
+ nwlRequest = smb_allWaitingLocks;
+ if (nwlRequest == NULL) {
osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
thrd_Sleep(1000);
continue;
- }
- else first = 1;
+ } else
+ first = 1;
+
do {
if (first)
first = 0;
else
lock_ObtainWrite(&smb_globalLock);
- wL = nwL;
- nwL = (smb_waitingLock_t *) osi_QNext(&wL->q);
+
+ 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;
+
+ /* 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;
+
+ 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 {
+ 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);
}
}
/* parse input parameters */
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
passwordp = smb_ParseASCIIBlock(tp, &tp);
tp = strrchr(pathp, '\\');
if (!tp)
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
osi_assert(pathp != NULL);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
osi_assert(statBlockp != NULL);
if (statLen == 0) {
long code = 0;
cm_scache_t *scp;
char *dptr;
- time_t dosTime;
+ afs_uint32 dosTime;
u_short shortTemp;
char attr;
smb_dirListPatch_t *patchp;
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
/* copy out time */
- shortTemp = dosTime & 0xffff;
+ shortTemp = (unsigned short) (dosTime & 0xffff);
*((u_short *)dptr) = shortTemp;
dptr += 2;
/* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
+ shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
*((u_short *)dptr) = shortTemp;
dptr += 2;
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;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
/* bail out if request looks bad */
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
- ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */
+ ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
/* make sure we got a whole search status */
if (dataLength < 21) {
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);
scp = dsp->scp;
cm_HoldSCache(scp);
code = 0;
- }
- else {
+ } else {
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, NULL, pathp);
- lock_ReleaseMutex(&dsp->mx);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
lock_ReleaseMutex(&dsp->mx);
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);
- lock_ObtainMutex(&dsp->mx);
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
/* 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) {
lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
lock_ReleaseRead(&scp->bufCreateLock);
+ lock_ObtainMutex(&dsp->mx);
/* now, if we're doing a star match, do bulk fetching of all of
* the status info for files in the dir.
*/
if (starPattern) {
- smb_ApplyDirListPatches(&dirListPatchesp, userp,
- &req);
+ smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+ lock_ObtainMutex(&scp->mx);
if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
LargeIntegerGreaterThanOrEqualTo(thyper,
scp->bulkStatProgress)) {
} else
cm_TryBulkStat(scp, &thyper, userp, &req);
}
+ } else {
+ lock_ObtainMutex(&scp->mx);
}
-
- lock_ObtainMutex(&scp->mx);
- if (code)
+ lock_ReleaseMutex(&dsp->mx);
+ if (code) {
+ osi_Log2(smb_logp, "SMB search dir buf_Get scp %x failed %d", scp, code);
break;
+ }
+
bufferOffset = thyper;
/* now get the data in the cache */
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;
+ 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;
* never hurts to be sure.
*/
strncpy(op, actualName, 13);
+ if (smb_StoreAnsiFilenames)
+ CharToOem(op, op);
/* Uppercase if requested by client */
- if ((((smb_t *)inp)->flg2 & 1) == 0)
+ if (!KNOWS_LONG_NAMES(inp))
_strupr(op);
op += 13;
pathp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(pathp, NULL);
+ if (!pathp)
+ return CM_ERROR_BADFD;
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive check path %s",
osi_LogSaveString(smb_logp, pathp));
-
- if (!pathp) {
- return CM_ERROR_BADFD;
- }
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
userp = smb_GetUser(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;
}
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,
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;
pathp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(pathp, NULL);
-
- if (!pathp) {
+ if (!pathp)
return CM_ERROR_BADSMB;
- }
-
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
+
osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
dosTime, attribute);
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
userp = smb_GetUser(vcp, inp);
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.
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;
pathp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(pathp, NULL);
-
- if (!pathp) {
+ if (!pathp)
return CM_ERROR_BADSMB;
- }
if (*pathp == 0) /* null path */
pathp = "\\";
+ else
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
osi_LogSaveString(smb_logp, pathp));
- rootScp = cm_rootSCachep;
+ rootScp = cm_data.rootSCachep;
userp = smb_GetUser(vcp, inp);
*/
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastComp, pathp);
+#ifndef SPECIAL_FOLDERS
if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
code = cm_NameI(rootScp, spacep->data,
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);
}
}
}
+#endif /* SPECIAL_FOLDERS */
code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
tidPathp, &req, &newScp);
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,
smb_SetSMBParm(outp, 0, attrs);
smb_DosUTimeFromUnixTime(&dosTime, newScp->clientModTime);
- smb_SetSMBParm(outp, 1, dosTime & 0xffff);
- smb_SetSMBParm(outp, 2, (dosTime>>16) & 0xffff);
+ smb_SetSMBParm(outp, 1, (unsigned int)(dosTime & 0xffff));
+ smb_SetSMBParm(outp, 2, (unsigned int)((dosTime>>16) & 0xffff));
smb_SetSMBParm(outp, 3, newScp->length.LowPart & 0xffff);
smb_SetSMBParm(outp, 4, (newScp->length.LowPart >> 16) & 0xffff);
smb_SetSMBParm(outp, 5, 0);
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;
pathp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(pathp, NULL);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
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);
smb_SetSMBParm(outp, 0, fidp->fid);
smb_SetSMBParm(outp, 1, smb_Attributes(scp));
smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
- smb_SetSMBParm(outp, 2, dosTime & 0xffff);
- smb_SetSMBParm(outp, 3, (dosTime >> 16) & 0xffff);
+ smb_SetSMBParm(outp, 2, (unsigned int)(dosTime & 0xffff));
+ smb_SetSMBParm(outp, 3, (unsigned int)((dosTime >> 16) & 0xffff));
smb_SetSMBParm(outp, 4, scp->length.LowPart & 0xffff);
smb_SetSMBParm(outp, 5, (scp->length.LowPart >> 16) & 0xffff);
/* pass the open mode back; XXXX add access checks */
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
osi_Log1(smb_logp, "SMB receive unlink %s",
osi_LogSaveString(smb_logp, pathp));
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;
* 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;
}
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. */
tp = smb_GetSMBData(inp, NULL);
oldPathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(oldPathp,oldPathp);
newPathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(newPathp,newPathp);
osi_Log2(smb_logp, "smb rename [%s] to [%s]",
osi_LogSaveString(smb_logp, oldPathp),
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
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;
rock.name = pathp;
rock.vnode = scp;
- code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL,
- userp, reqp, NULL);
+ code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL);
if (code == CM_ERROR_STOPNOW)
*newPathp = rock.fullName;
else
unsigned short fid;
smb_fid_t *fidp;
cm_user_t *userp;
- long dosTime;
+ afs_uint32 dosTime;
long code = 0;
cm_req_t req;
else
code = 0;
+ /* unlock any pending locks */
+ if (!(fidp->flags & SMB_FID_IOCTL) && fidp->scp &&
+ fidp->scp->fileType == CM_SCACHETYPE_FILE) {
+ cm_key_t key;
+ unsigned pid;
+ cm_scache_t * scp;
+ long tcode;
+
+ pid = ((smb_t *) inp)->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fid);
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+ 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_LOCK);
+
+ post_syncopdone:
+
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseSCache(scp);
+ }
+
if (fidp->flags & SMB_FID_DELONCLOSE) {
cm_scache_t *dscp = fidp->NTopen_dscp;
char *pathp = fidp->NTopen_pathp;
}
if (fidp->curr_chunk == fidp->prev_chunk + 1)
sequential = 1;
- }
+ }
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
/* 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 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 */
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;
/* 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;
*/
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 */
writeBackOffset.HighPart, cm_chunkSize, 0, userp);
}
- osi_Log2(smb_logp, "smb_WriteData fid %d returns %d written %d",
+ osi_Log3(smb_logp, "smb_WriteData fid %d returns %d written %d",
fidp->fid, code, *writtenp);
return code;
}
osi_hyper_t offset;
long count, written = 0, total_written = 0;
unsigned short fd;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp;
userp = smb_GetUser(vcp, inp);
- /* special case: 0 bytes transferred means truncate to this position */
+ /* special case: 0 bytes transferred means truncate to this position */
if (count == 0) {
cm_req_t req;
goto done;
}
+ {
+ 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)
+ goto done;
+ }
+
/*
* Work around bug in NT client
*
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);
osi_hyper_t offset;
long count, finalCount;
unsigned short fd;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp;
if (fidp->flags & SMB_FID_IOCTL) {
return smb_IoctlRead(fidp, vcp, inp, outp);
}
+
+ {
+ 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;
+
+ 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);
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
if (strcmp(pathp, "\\") == 0)
return CM_ERROR_EXISTS;
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;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
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.
*/
- if (!lastNamep) lastNamep = pathp;
- else lastNamep++;
+ if (!lastNamep)
+ lastNamep = pathp;
+ else
+ lastNamep++;
if (!smb_IsLegalFilename(lastNamep))
return CM_ERROR_BADNTFILENAME;
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_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp 0x%x lana %d lsn %d",(int)vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch %s vcp 0x%x 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_LogEvent("AFS Dispatch return",NULL,"Code 0x%x",(code==0)?0:code-CM_ERROR_BASE);
+ osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%x lana %d lsn %d",(code==0)?0:code-CM_ERROR_BASE,vcp,vcp->lana,vcp->lsn);
#ifdef LOG_PACKET
if ( code == CM_ERROR_BADSMB ||
code == CM_ERROR_BADOP )
smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
- smbp->flg2 |= 0x4000;
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
break;
}
else {
/* now send the output packet, and return */
if (!noSend)
smb_SendPacket(vcp, outp);
- thrd_Decrement(&ongoingOps);
+ thrd_Decrement(&ongoingOps);
- if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
- if (active_vcp) {
- smb_ReleaseVC(active_vcp);
- osi_Log2(smb_logp,
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ if (active_vcp != vcp) {
+ if (active_vcp) {
+ smb_ReleaseVC(active_vcp);
+ osi_Log2(smb_logp,
"Replacing active_vcp %x with %x", active_vcp, vcp);
- }
- smb_HoldVC(vcp);
+ }
+ smb_HoldVC(vcp);
active_vcp = vcp;
- last_msg_time = GetCurrentTime();
- }
- else if (active_vcp == vcp) {
- smb_ReleaseVC(active_vcp);
- active_vcp = NULL;
+ }
+ last_msg_time = GetCurrentTime();
+ } else if (active_vcp == vcp) {
+ smb_ReleaseVC(active_vcp);
+ active_vcp = NULL;
}
return;
DWORD code;
int idx;
- while (1) {
+ while (smbShutdownFlag == 0) {
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBevents,
FALSE, INFINITE);
if (code == WAIT_OBJECT_0)
dos_ptr dos_ncb;
#endif /* DJGPP */
- while (1) {
+ while (smbShutdownFlag == 0) {
/* Get a session */
code = thrd_WaitForMultipleObjects_Event(numSessions, SessionEvents,
FALSE, INFINITE);
NCBretry:
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBavails,
FALSE, INFINITE);
- if (code == WAIT_OBJECT_0)
- goto NCBretry;
+ if (code == WAIT_OBJECT_0) {
+ if (smbShutdownFlag == 1)
+ break;
+ else
+ goto NCBretry;
+ }
/* error checking */
if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
/* Fire it up */
ncbp = NCBs[idx_NCB];
-#ifdef DJGPP
- dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
ncbp->ncb_lsn = (unsigned char) LSNs[idx_session];
ncbp->ncb_command = NCBRECV | ASYNCH;
ncbp->ncb_lana_num = lanas[idx_session];
((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 */
}
dos_ptr dos_ncb;
#endif /* DJGPP */
+ rx_StartClientThread();
+
outncbp = GetNCB();
outbufp = GetPacket();
outbufp->ncbp = outncbp;
while (1) {
code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
FALSE, INFINITE);
+
+ /* terminate silently if shutdown flag is set */
if (code == WAIT_OBJECT_0) {
- continue;
+ if (smbShutdownFlag == 1) {
+ thrd_SetEvent(smb_ServerShutdown[myIdx]);
+ break;
+ } else
+ continue;
}
/* error checking */
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);
}
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);
+ if (rc != NRC_PENDING && rc != NRC_GOODRET) {
+ switch (rc) {
+ case 0x01:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal buffer length", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x03:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal command", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x05:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command timed out", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x06:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: message incomplete, issue another command", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x07:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal buffer address", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x08:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session number out of range", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x09:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no resource available", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x0a:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session closed", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x0b:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command cancelled", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x0d:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: duplicate name", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x0e:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name table full", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x0f:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no deletions, name has active lsn %d sessions", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x11:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: local session table full", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x12:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: remote session table full", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x13:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal name number", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x14:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no callname", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x15:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: cannot put * in NCB_NAME", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x16:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name in use on remote adapter", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x17:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name deleted", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x18:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session ended abnormally", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x19:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name conflict detected", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x21:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: interface busy, IRET before retrying", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x22:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: too many commands outstanding, retry later", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x23:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: ncb_lana_num field invalid", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x24:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command completed while cancel occurring", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x26:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command not valid to cancel", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x30:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name defined by anther local process", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x34:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: environment undefined. RESET required", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x35:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: required OS resources exhausted", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x36:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: max number of applications exceeded", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x37:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no saps available for netbios", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x38:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: requested resources are not available", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x39:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: invalid ncb address or length > segment", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x3B:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: invalid NCB DDID", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x3C:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: lock of user area failed", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x3f:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: NETBIOS not loaded", ncbp->ncb_lsn, idx_session);
+ break;
+ case 0x40:
+ osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: system error", ncbp->ncb_lsn, idx_session);
+ break;
+ default:
+ osi_Log3(smb_logp, "NCBRECV failure lsn %d session %d code %d", ncbp->ncb_lsn, idx_session, rc);
+ break;
+ }
+ }
switch (rc) {
- case NRC_GOODRET: break;
+ case NRC_GOODRET:
+ 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:
/* Client closed session */
- if (reportSessionStartups)
- {
- osi_Log1(smb_logp, "session [ %d ] closed", idx_session);
- }
dead_sessions[idx_session] = TRUE;
if (vcp)
smb_ReleaseVC(vcp);
* 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",
+ if (dead_vcp == vcp)
+ osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp);
+ else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
vcp, vcp->usersp);
smb_HoldVC(vcp);
+ if (dead_vcp) {
+ smb_ReleaseVC(dead_vcp);
+ osi_Log1(smb_logp,
+ "Previous dead_vcp %x", dead_vcp);
+ }
dead_vcp = vcp;
vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
}
* Either way, we can't do anything with this packet.
* Log, sleep and resume.
*/
- if(!vcp) {
+ if (!vcp) {
HANDLE h;
char buf[1000];
char *ptbuf[1];
ptbuf[0] = buf;
h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
- if(h) {
+ if (h) {
ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,sizeof(*ncbp),ptbuf,(void*)ncbp);
DeregisterEventSource(h);
}
smb_concurrentCalls--;
-doneWithNCB:
+ doneWithNCB:
thrd_SetEvent(NCBavails[idx_NCB]);
}
if (vcp)
}
afsd_ForceTrace(TRUE);
+ buf_ForceTrace(TRUE);
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
long code = 0;
long len;
long i, j;
- smb_vc_t *vcp;
+ smb_vc_t *vcp = 0;
int flags = 0;
char rname[NCBNAMSZ+1];
char cname[MAX_COMPUTERNAME_LENGTH+1];
}
}
- /* 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.
- */
+ if (i >= Sessionmax - 1 || numNCBs >= NCBmax - 1) {
+ unsigned long code = CM_ERROR_ALLBUSY;
+ smb_packet_t * outp = GetPacket();
+ unsigned char *outWctp;
+ smb_t *smbp;
+
+ 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);
+ } else {
+ /* assert that we do not exceed the maximum number of sessions or NCBs.
+ * we should probably want to wait for a session to be freed in case
+ * we run out.
+ */
+ osi_assert(i < Sessionmax - 1);
+ osi_assert(numNCBs < NCBmax - 1); /* if we pass this test we can allocate one more */
- LSNs[i] = ncbp->ncb_lsn;
- lanas[i] = ncbp->ncb_lana_num;
+ 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]);
- } else {
- thrd_SetEvent(SessionEvents[i]);
+ 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]);
+ } else {
+ thrd_SetEvent(SessionEvents[i]);
+ }
}
+
+ smb_ReleaseVC(vcp);
+
/* unlock */
lock_ReleaseMutex(&smb_ListenerLock);
-
} /* dispatch while loop */
}
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);
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
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++) {
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);
+ afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
#ifdef DJGPP
/* we only use one LANA with djgpp */
lana_list.lana[0] = lana;
#endif
}
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);
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__);
}
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 */
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();
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 )
NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
NCBreturns[i][0] = retHandle;
}
- for (i = 1; i <= nThreads; i++)
- InitNCBslot(i);
- numNCBs = nThreads + 1;
+
+ smb_ServerShutdown = malloc(smb_NumServerThreads * sizeof(EVENT_HANDLE));
+ for (i = 0; i < smb_NumServerThreads; i++) {
+ sprintf(eventName, "smb_ServerShutdown[%d]", i);
+ smb_ServerShutdown[i] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ afsi_log("Event Object Already Exists: %s", eventName);
+ InitNCBslot(i+1);
+ }
+ numNCBs = smb_NumServerThreads + 1;
/* Initialize dispatch table */
memset(&smb_dispatchTable, 0, sizeof(smb_dispatchTable));
smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
smb_tran2DispatchTable[13].procp = smb_ReceiveTran2CreateDirectory;
smb_tran2DispatchTable[14].procp = smb_ReceiveTran2SessionSetup;
- smb_tran2DispatchTable[14].procp = smb_ReceiveTran2GetDFSReferral;
- smb_tran2DispatchTable[14].procp = smb_ReceiveTran2ReportDFSInconsistency;
+ smb_tran2DispatchTable[16].procp = smb_ReceiveTran2GetDFSReferral;
+ smb_tran2DispatchTable[17].procp = smb_ReceiveTran2ReportDFSInconsistency;
/* setup the rap dispatch table */
memset(smb_rapDispatchTable, 0, sizeof(smb_rapDispatchTable));
/* 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*/
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.MaximumLength = smb_lsaLogonOrigin.Length + 1;
} else {
afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",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);
- }
- 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);
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);
#endif
long code = 0;
int i;
+ smb_vc_t *vcp;
/*fprintf(stderr, "Entering smb_Shutdown\n");*/
#ifndef DJGPP
code = Netbios(ncbp);
#else
- code = Netbios(ncbp, dos_ncb);
+ 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;
}
}
+ /* 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++) {
}
fflush(stderr);
}
+
+ /* 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;
+
+ 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 (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);
}
/* Get the UNC \\<servername>\<sharename> prefix. */
#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 vcpsp\n");
+ sprintf(output, "begin dumping smb_vc_t\n");
WriteFile(outputFile, output, strlen(output), &zilch, NULL);
- for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
+ for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
WriteFile(outputFile, output, strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping fidsp\n");
+ sprintf(output, "begin dumping smb_fid_t\n");
WriteFile(outputFile, output, 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%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, 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);
}
- sprintf(output, "done dumping fidsp\n");
+ sprintf(output, "done dumping smb_fid_t\n");
WriteFile(outputFile, output, strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping vcpsp\n");
+ sprintf(output, "done dumping smb_vc_t\n");
WriteFile(outputFile, output, strlen(output), &zilch, NULL);
- lock_ReleaseRead(&smb_rctLock);
+ if (lock)
+ lock_ReleaseRead(&smb_rctLock);
return 0;
}