diff --git a/src/WINNT/afsd/afsd.h b/src/WINNT/afsd/afsd.h index 218777fc10..45dac47389 100644 --- a/src/WINNT/afsd/afsd.h +++ b/src/WINNT/afsd/afsd.h @@ -127,7 +127,7 @@ extern long rx_mtu; extern HANDLE WaitToTerminate; -#undef DFS_SUPPORT +#define DFS_SUPPORT 1 #define LOG_PACKET 1 #undef NOTSERVICE #define LOCK_TESTING 1 diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index 328e16ece6..0f7e478340 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -1305,6 +1305,9 @@ afsd_Main(DWORD argc, LPTSTR *argv) SetServiceStatus(StatusHandle, &ServiceStatus); #endif + /* Notify any volume status handlers that the cache manager has started */ + cm_VolStatus_Service_Started(); + /* the following ifdef chooses the mode of operation for the service. to enable * a runtime flag (instead of compile-time), pioctl() would need to dynamically * determine the mode, in order to use the correct ioctl special-file path. */ @@ -1367,9 +1370,6 @@ afsd_Main(DWORD argc, LPTSTR *argv) LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING); } - /* Notify any volume status handlers that we have started */ - cm_VolStatus_Service_Started(); - /* allow an exit to be called when started */ hHookDll = LoadLibrary(AFSD_HOOK_DLL); if (hHookDll) diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index f2b38a8404..d2c9bbbcd8 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -303,6 +303,7 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_NOT_A_DFSLINK (CM_ERROR_BASE+53) #define CM_ERROR_INEXACT_MATCH (CM_ERROR_BASE+54) #define CM_ERROR_BPLUS_NOMATCH (CM_ERROR_BASE+55) +#define CM_ERROR_EAS_NOT_SUPPORTED (CM_ERROR_BASE+56) /* Used by cm_FollowMountPoint and cm_GetVolumeByName */ #define RWVOL 0 diff --git a/src/WINNT/afsd/cm_conn.h b/src/WINNT/afsd/cm_conn.h index f127254ca4..5cfd346190 100644 --- a/src/WINNT/afsd/cm_conn.h +++ b/src/WINNT/afsd/cm_conn.h @@ -32,13 +32,19 @@ typedef struct cm_conn { #define CM_CONN_FLAG_FORCE_NEW 1 -/* structure used for tracking RPC progress */ +/* + * structure used for tracking RPC progress + * and for passing path info from the smb layer + * to the cache manager functions. + */ typedef struct cm_req { DWORD startTime; /* Quit before RDR times us out */ int rpcError; /* RPC error code */ int volumeError; /* volume error code */ int accessError; /* access error code */ int flags; + char * tidPathp; + char * relPathp; } cm_req_t; /* flags in cm_req structure */ diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index da578118aa..67fb3e45e6 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -476,7 +476,7 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp, long code; osi_hyper_t thyper; cm_buf_t *bufferp; - cm_dirEntry_t *dep; + cm_dirEntry_t *dep = 0; unsigned short *hashTable; unsigned int i, idx; int BeyondPage = 0, HaveDot = 0, HaveDotDot = 0; @@ -575,7 +575,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp, { char *tp; long code; - cm_dirEntry_t *dep; + cm_dirEntry_t *dep = 0; cm_buf_t *bufferp; long temp; osi_hyper_t dirLength; @@ -1719,6 +1719,9 @@ long cm_HandleLink(cm_scache_t *linkScp, cm_user_t *userp, cm_req_t *reqp) if (!linkScp->mountPointStringp[0]) { strncpy(linkScp->mountPointStringp, bufp->datap, temp); linkScp->mountPointStringp[temp] = 0; /* null terminate */ + + if ( !strnicmp(linkScp->mountPointStringp, "msdfs:", strlen("msdfs:")) ) + linkScp->fileType = CM_SCACHETYPE_DFSLINK; } buf_Release(bufp); } /* don't have sym link contents cached */ @@ -1741,9 +1744,12 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp, char *linkp; cm_space_t *tsp; + *newRootScpp = NULL; + *newSpaceBufferp = NULL; + lock_ObtainMutex(&linkScp->mx); code = cm_HandleLink(linkScp, userp, reqp); - if (code) + if (code) goto done; /* if we may overflow the buffer, bail out; buffer is signficantly @@ -1780,13 +1786,12 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp, } else { linkScp->fileType = CM_SCACHETYPE_DFSLINK; strcpy(tsp->data, linkp); - *newRootScpp = NULL; code = CM_ERROR_PATH_NOT_COVERED; } - } else if ( !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) { + } else if ( linkScp->fileType == CM_SCACHETYPE_DFSLINK || + !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) { linkScp->fileType = CM_SCACHETYPE_DFSLINK; strcpy(tsp->data, linkp); - *newRootScpp = NULL; code = CM_ERROR_PATH_NOT_COVERED; } else if (*linkp == '\\' || *linkp == '/') { #if 0 @@ -1802,19 +1807,24 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp, */ linkScp->fileType = CM_SCACHETYPE_INVALID; strcpy(tsp->data, linkp); - *newRootScpp = NULL; code = CM_ERROR_NOSUCHPATH; #endif } else { /* a relative link */ strcpy(tsp->data, linkp); - *newRootScpp = NULL; } if (pathSuffixp[0] != 0) { /* if suffix string is non-null */ strcat(tsp->data, "\\"); strcat(tsp->data, pathSuffixp); } - *newSpaceBufferp = tsp; + if (code == 0) + *newSpaceBufferp = tsp; + else { + cm_FreeSpace(tsp); + + if (code == CM_ERROR_PATH_NOT_COVERED && reqp->tidPathp && reqp->relPathp) + cm_VolStatus_Notify_DFS_Mapping(linkScp, reqp->tidPathp, reqp->relPathp); + } done: lock_ReleaseMutex(&linkScp->mx); diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index ac9d59f3f4..b376efdaaf 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -189,6 +189,10 @@ extern long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, extern long cm_EvaluateSymLink(cm_scache_t *dscp, cm_scache_t *linkScp, cm_scache_t **outScpp, cm_user_t *userp, cm_req_t *reqp); +extern long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp, + cm_req_t *reqp, cm_scache_t **outScpp); + + extern long cm_Lock(cm_scache_t *scp, unsigned char sLockType, LARGE_INTEGER LOffset, LARGE_INTEGER LLength, cm_key_t key, int allowWait, cm_user_t *userp, cm_req_t *reqp, diff --git a/src/WINNT/afsd/cm_volstat.c b/src/WINNT/afsd/cm_volstat.c index 25af0c96ec..328ca3c728 100644 --- a/src/WINNT/afsd/cm_volstat.c +++ b/src/WINNT/afsd/cm_volstat.c @@ -46,6 +46,14 @@ HMODULE hVolStatus = NULL; dll_VolStatus_Funcs_t dll_funcs; cm_VolStatus_Funcs_t cm_funcs; +static char volstat_NetbiosName[64] = ""; + +afs_uint32 +cm_VolStatus_Active(void) +{ + return (hVolStatus != NULL); +} + /* This function is used to load any Volume Status Handlers * and their associated function pointers. */ @@ -64,6 +72,12 @@ cm_VolStatus_Initialization(void) dummyLen = sizeof(wd); code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL, (BYTE *) &wd, &dummyLen); + + if (code == 0) { + dummyLen = sizeof(volstat_NetbiosName); + code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL, + (BYTE *)volstat_NetbiosName, &dummyLen); + } RegCloseKey (parmKey); } @@ -76,6 +90,7 @@ cm_VolStatus_Initialization(void) cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID; cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink; + dll_funcs.version = DLL_VOLSTATUS_FUNCS_VERSION; code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs); } @@ -87,6 +102,8 @@ cm_VolStatus_Initialization(void) } } + osi_Log1(afsd_logp,"cm_VolStatus_Initialization 0x%x", code); + return code; } @@ -96,6 +113,8 @@ cm_VolStatus_Initialization(void) long cm_VolStatus_Finalize(void) { + osi_Log1(afsd_logp,"cm_VolStatus_Finalize handle 0x%x", hVolStatus); + if (hVolStatus == NULL) return 0; @@ -113,6 +132,8 @@ cm_VolStatus_Service_Started(void) { long code = 0; + osi_Log1(afsd_logp,"cm_VolStatus_Service_Started handle 0x%x", hVolStatus); + if (hVolStatus == NULL) return 0; @@ -131,6 +152,8 @@ cm_VolStatus_Service_Stopped(void) { long code = 0; + osi_Log1(afsd_logp,"cm_VolStatus_Service_Stopped handle 0x%x", hVolStatus); + if (hVolStatus == NULL) return 0; @@ -225,22 +248,68 @@ cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volst } -long __fastcall -cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID) + +long +cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp, char *tidPathp, char *pathp) { - afs_uint32 code; + long code = 0; + char src[1024], *p; + size_t len; + + if (hVolStatus == NULL || dll_funcs.version < 2) + return 0; + + snprintf(src,sizeof(src), "\\\\%s%s", volstat_NetbiosName, tidPathp); + len = strlen(src); + if ((src[len-1] == '\\' || src[len-1] == '/') && + (pathp[0] == '\\' || pathp[0] == '/')) + strncat(src, &pathp[1], sizeof(src)); + else + strncat(src, pathp, sizeof(src)); + + for ( p=src; *p; p++ ) { + if (*p == '/') + *p = '\\'; + } + + code = dll_funcs.dll_VolStatus_Notify_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique, + src, scp->mountPointStringp); + + return code; +} + +long +cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp) +{ + long code = 0; + + if (hVolStatus == NULL || dll_funcs.version < 2) + return 0; + + code = dll_funcs.dll_VolStatus_Invalidate_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique); + + return code; +} + + +long __fastcall +cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus) +{ + afs_uint32 code = 0; cm_req_t req; cm_scache_t *scp; if (cellID == NULL || volID == NULL) return CM_ERROR_INVAL; + osi_Log2(afsd_logp,"cm_VolStatus_Path_To_ID share %s path %s", + osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path)); + cm_InitReq(&req); - - code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp); + code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp); if (code) - return code; + goto done; lock_ObtainMutex(&scp->mx); code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0, @@ -248,24 +317,27 @@ cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cell if (code) { lock_ReleaseMutex(&scp->mx); cm_ReleaseSCache(scp); - return code; + goto done; } cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); *cellID = scp->fid.cell; *volID = scp->fid.volume; + *pstatus = cm_GetVolumeStatus(scp->volp, scp->fid.volume); lock_ReleaseMutex(&scp->mx); cm_ReleaseSCache(scp); - return 0; + done: + osi_Log1(afsd_logp,"cm_VolStatus_Path_To_ID code 0x%x",code); + return code; } long __fastcall cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer) { - afs_uint32 code; + afs_uint32 code = 0; cm_req_t req; cm_scache_t *scp; size_t len; @@ -273,11 +345,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 * if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0)) return CM_ERROR_INVAL; + osi_Log2(afsd_logp,"cm_VolStatus_Path_To_DFSlink share %s path %s", + osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path)); + cm_InitReq(&req); - code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp); + code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + cm_rootUserp, (char *)share, &req, &scp); if (code) - return code; + goto done; lock_ObtainMutex(&scp->mx); code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0, @@ -285,13 +361,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 * if (code) { lock_ReleaseMutex(&scp->mx); cm_ReleaseSCache(scp); - return code; + goto done; } cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); - if (scp->fileType != CM_SCACHETYPE_DFSLINK) - return CM_ERROR_NOT_A_DFSLINK; + if (scp->fileType != CM_SCACHETYPE_DFSLINK) { + code = CM_ERROR_NOT_A_DFSLINK; + goto done; + } len = strlen(scp->mountPointStringp) + 1; if (pBuffer == NULL) @@ -299,11 +377,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 * else if (*pBufSize >= len) { strcpy(pBuffer, scp->mountPointStringp); *pBufSize = len; - } else + } else { code = CM_ERROR_TOOBIG; + goto done; + } lock_ReleaseMutex(&scp->mx); cm_ReleaseSCache(scp); - return 0; + done: + osi_Log1(afsd_logp,"cm_VolStatus_Path_To_DFSlink code 0x%x",code); + return code; } diff --git a/src/WINNT/afsd/cm_volstat.h b/src/WINNT/afsd/cm_volstat.h index 877d37c702..8d20cad389 100644 --- a/src/WINNT/afsd/cm_volstat.h +++ b/src/WINNT/afsd/cm_volstat.h @@ -55,25 +55,36 @@ extern long cm_VolStatus_Network_Addr_Change(void); extern long cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status); -extern long __fastcall cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID); +extern long __fastcall cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus); extern long __fastcall cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer); -#define DLL_VOLSTATUS_FUNCS_VERSION 1 +extern long cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp, char *tidPathp, char *pathp); + +extern long cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp); + +#define DLL_VOLSTATUS_FUNCS_VERSION 2 typedef struct dll_VolStatus_Funcs { afs_uint32 version; + /* version 1 */ long (__fastcall * dll_VolStatus_Service_Started)(void); long (__fastcall * dll_VolStatus_Service_Stopped)(void); long (__fastcall * dll_VolStatus_Network_Started)(const char *netbios32, const char *netbios64); long (__fastcall * dll_VolStatus_Network_Stopped)(const char *netbios32, const char *netbios64); long (__fastcall * dll_VolStatus_Network_Addr_Change)(void); long (__fastcall * dll_VolStatus_Change_Notification)(afs_uint32 cellID, afs_uint32 volID, enum volstatus status); + /* version 2 */ + long (__fastcall * dll_VolStatus_Notify_DFS_Mapping)(afs_uint32 cellID, afs_uint32 volID, + afs_uint32 vnodeID, afs_uint32 uniqID, + char *src, char *target); + long (__fastcall * dll_VolStatus_Invalidate_DFS_Mapping)(afs_uint32 cellID, afs_uint32 volID, + afs_uint32 vnodeID, afs_uint32 uniqID); } dll_VolStatus_Funcs_t; #define CM_VOLSTATUS_FUNCS_VERSION 1 typedef struct cm_VolStatus_Funcs { afs_uint32 version; - long (__fastcall * cm_VolStatus_Path_To_ID)(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID); + long (__fastcall * cm_VolStatus_Path_To_ID)(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus); long (__fastcall * cm_VolStatus_Path_To_DFSlink)(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer); } cm_VolStatus_Funcs_t; diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 8597476fd8..6021e6c006 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -2876,23 +2876,12 @@ void smb_MapNTError(long code, unsigned long *NTStatusp) 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 */ + NTStatus = 0xC000022DL; /* Retry */ } 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 */ } @@ -3891,23 +3880,31 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp) /* mask starts out all blanks */ memset(maskp, ' ', 11); + maskp[11] = '\0'; /* find last backslash, or use whole thing if there is none */ tp = strrchr(pathp, '\\'); - if (!tp) tp = pathp; - else tp++; /* skip slash */ + if (!tp) + tp = pathp; + else + tp++; /* skip slash */ up = maskp; /* names starting with a dot are illegal */ - if (*tp == '.') valid8Dot3 = 0; + if (*tp == '.') + valid8Dot3 = 0; for(i=0;; i++) { tc = *tp++; - if (tc == 0) return valid8Dot3; - if (tc == '.' || tc == '"') break; - if (i < 8) *up++ = tc; - else valid8Dot3 = 0; + if (tc == 0) + return valid8Dot3; + if (tc == '.' || tc == '"') + break; + if (i < 8) + *up++ = tc; + else + valid8Dot3 = 0; } /* if we get here, tp point after the dot */ @@ -3986,7 +3983,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t { unsigned char *pathp; unsigned char *tp; - unsigned char mask[11]; + unsigned char mask[12]; unsigned char *statBlockp; unsigned char initStatBlock[21]; int statLen; @@ -4052,8 +4049,10 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t return 0; } -long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp, - cm_user_t *userp, cm_req_t *reqp) +static long +smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp, + char * tidPathp, char * relPathp, + cm_user_t *userp, cm_req_t *reqp) { long code = 0; cm_scache_t *scp; @@ -4063,13 +4062,20 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp, char attr; smb_dirListPatch_t *patchp; smb_dirListPatch_t *npatchp; + char path[AFSPATHMAX]; for (patchp = *dirPatchespp; patchp; patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) { dptr = patchp->dptr; + snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name); + reqp->relPathp = path; + reqp->tidPathp = tidPathp; + code = cm_GetSCache(&patchp->fid, &scp, userp, reqp); + reqp->relPathp = reqp->tidPathp = NULL; + if (code) { if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) *dptr++ = SMB_ATTR_HIDDEN; @@ -4133,7 +4139,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou char *tp; long code = 0; char *pathp; - cm_dirEntry_t *dep; + cm_dirEntry_t *dep = 0; int maxCount; smb_dirListPatch_t *dirListPatchesp; smb_dirListPatch_t *curPatchp; @@ -4156,7 +4162,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou char shortName[13]; char *actualName; char *shortNameEnd; - char mask[11]; + char mask[12]; int returnedNames; long nextEntryCookie; int numDirChunks; /* # of 32 byte dir chunks in this entry */ @@ -4167,7 +4173,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou int starPattern; int rootPath = 0; int caseFold; - char *tidPathp; + char *tidPathp = 0; cm_req_t req; cm_fid_t fid; int fileType; @@ -4218,7 +4224,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou dsp = smb_NewDirSearch(0); dsp->attribute = attribute; smb_Get8Dot3MaskFromPath(mask, pathp); - memcpy(dsp->mask, mask, 11); + memcpy(dsp->mask, mask, 12); /* track if this is likely to match a lot of entries */ if (smb_IsStarMask(mask)) @@ -4244,7 +4250,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou */ memcpy(&clientCookie, &inCookiep[17], 4); - memcpy(mask, dsp->mask, 11); + memcpy(mask, dsp->mask, 12); /* assume we're doing a star match if it has continued for more * than one call. @@ -4275,17 +4281,21 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou smb_ReleaseDirSearch(dsp); return CM_ERROR_NOFILES; } + strcpy(dsp->tidPath, tidPathp ? tidPathp : "/"); + strcpy(dsp->relPath, spacep->data); + code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp); if (code == 0) { #ifdef DFS_SUPPORT if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data); cm_ReleaseSCache(scp); lock_ReleaseMutex(&dsp->mx); cm_ReleaseUser(userp); smb_DeleteDirSearch(dsp); smb_ReleaseDirSearch(dsp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -4409,7 +4419,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou * the status info for files in the dir. */ if (starPattern) { - smb_ApplyDirListPatches(&dirListPatchesp, userp, &req); + smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req); lock_ObtainMutex(&scp->mx); if ((dsp->flags & SMB_DIRSEARCH_BULKST) && LargeIntegerGreaterThanOrEqualTo(thyper, @@ -4632,7 +4642,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou /* apply and free last set of patches; if not doing a star match, this * will be empty, but better safe (and freeing everything) than sorry. */ - smb_ApplyDirListPatches(&dirListPatchesp, userp, &req); + smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req); /* special return code for unsuccessful search */ if (code == 0 && dataLength < 21 && returnedNames == 0) @@ -4719,9 +4729,10 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou #ifdef DFS_SUPPORT if (newScp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp); cm_ReleaseSCache(newScp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -4806,9 +4817,10 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack #ifdef DFS_SUPPORT if (newScp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp); cm_ReleaseSCache(newScp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -4940,7 +4952,8 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack if (code == 0) { #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { - if ( WANTS_DFS_PATHNAMES(inp) ) + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -4974,9 +4987,10 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack #ifdef DFS_SUPPORT if (newScp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp); cm_ReleaseSCache(newScp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5129,9 +5143,10 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5243,11 +5258,11 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype cm_DirEntryListAdd(dep->name, &rockp->matches); - rockp->any = 1; + rockp->any = 1; - /* If we made a case sensitive exact match, we might as well quit now. */ - if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp)) - code = CM_ERROR_STOPNOW; + /* If we made a case sensitive exact match, we might as well quit now. */ + if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp)) + code = CM_ERROR_STOPNOW; else code = 0; } @@ -5305,9 +5320,10 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5466,9 +5482,10 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i #ifdef DFS_SUPPORT if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data); cm_ReleaseSCache(oldDscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5487,10 +5504,11 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i #ifdef DFS_SUPPORT if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data); cm_ReleaseSCache(oldDscp); cm_ReleaseSCache(newDscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5666,9 +5684,10 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) #ifdef DFS_SUPPORT if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data); cm_ReleaseSCache(oldDscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5686,10 +5705,11 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) #ifdef DFS_SUPPORT if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data); cm_ReleaseSCache(newDscp); cm_ReleaseSCache(oldDscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5891,9 +5911,10 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -7281,9 +7302,10 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -7405,9 +7427,10 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 57d3fe7a94..f312e3d409 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -460,6 +460,8 @@ typedef struct smb_dirSearch { * locked by smb_globalLock */ unsigned short attribute; /* search attribute * (used for extended protocol) */ + char tidPath[256]; /* tid path */ + char relPath[1024]; /* relative path */ char mask[256]; /* search mask for V3 */ } smb_dirSearch_t; diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 4398386e02..b082570212 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -1070,10 +1070,21 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o if (vcp->flags & SMB_VCFLAG_USENT) { int policy = smb_FindShareCSCPolicy(shareName); + HKEY parmKey; + DWORD code; + DWORD dwAdvertiseDFS = 0, dwSize = sizeof(DWORD); + + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + code = RegQueryValueEx(parmKey, "AdvertiseDFS", NULL, NULL, + (BYTE *)&dwAdvertiseDFS, &dwSize); + if (code != ERROR_SUCCESS) + dwAdvertiseDFS = 0; + RegCloseKey (parmKey); + } smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | -#ifdef DFS_SUPPORT - SMB_SHARE_IS_IN_DFS | -#endif + (dwAdvertiseDFS ? SMB_SHARE_IS_IN_DFS : 0) | (policy << 2)); } } else { @@ -2222,10 +2233,11 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); smb_FreeTran2Packet(outp); - if ( WANTS_DFS_PATHNAMES(p) ) + if ( WANTS_DFS_PATHNAMES(p) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -2251,10 +2263,11 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) } else { #ifdef DFS_SUPPORT if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); smb_FreeTran2Packet(outp); - if ( WANTS_DFS_PATHNAMES(p) ) + if ( WANTS_DFS_PATHNAMES(p) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -2627,6 +2640,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp, if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); + DebugBreak(); return CM_ERROR_PATH_NOT_COVERED; } #endif /* DFS_SUPPORT */ @@ -2770,7 +2784,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t if (code == 0) { #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { - if ( WANTS_DFS_PATHNAMES(p) ) + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); + if ( WANTS_DFS_PATHNAMES(p) || pnc ) code = CM_ERROR_PATH_NOT_COVERED; else code = CM_ERROR_BADSHARENAME; @@ -2816,9 +2831,10 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t #ifdef DFS_SUPPORT if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(p) ) + if ( WANTS_DFS_PATHNAMES(p) || pnc ) code = CM_ERROR_PATH_NOT_COVERED; else code = CM_ERROR_BADSHARENAME; @@ -2982,7 +2998,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet infoLevel != SMB_INFO_QUERY_ALL_EAS) { osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x", p->opcode, infoLevel); - smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL); + smb_SendTran2Error(vcp, p, opx, + infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL); return 0; } @@ -3040,7 +3057,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet if (code == 0) { #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { - if ( WANTS_DFS_PATHNAMES(p) ) + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); + if ( WANTS_DFS_PATHNAMES(p) || pnc ) code = CM_ERROR_PATH_NOT_COVERED; else code = CM_ERROR_BADSHARENAME; @@ -3162,7 +3180,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet } else if (infoLevel == SMB_INFO_QUERY_ALL_EAS) { /* we don't support EAs */ - code = CM_ERROR_INVAL; + code = CM_ERROR_EAS_NOT_SUPPORTED; } done: @@ -3575,11 +3593,14 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t long code = 0; int maxReferralLevel = 0; char requestFileName[1024] = ""; + char referralPath[1024] = ""; smb_tran2Packet_t *outp = 0; cm_user_t *userp = 0; + cm_scache_t *scp = 0; + cm_scache_t *dscp = 0; cm_req_t req; CPINFO CodePageInfo; - int i, nbnLen, reqLen; + int i, nbnLen, reqLen, refLen; int idx; cm_InitReq(&req); @@ -3596,57 +3617,152 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t nbnLen = strlen(cm_NetbiosName); reqLen = strlen(requestFileName); - if (reqLen == nbnLen + 5 && - requestFileName[0] == '\\' && + if (reqLen > nbnLen + 2 && requestFileName[0] == '\\' && !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) && - requestFileName[nbnLen+1] == '\\' && - (!_strnicmp("all",&requestFileName[nbnLen+2],3) || - !_strnicmp("*.",&requestFileName[nbnLen+2],2))) + requestFileName[nbnLen+1] == '\\') { - USHORT * sp; - struct smb_v2_referral * v2ref; - outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (reqLen + 8)); + int found = 0; - sp = (USHORT *)outp->datap; - idx = 0; - sp[idx++] = reqLen; /* path consumed */ - sp[idx++] = 1; /* number of referrals */ - sp[idx++] = 0x03; /* flags */ + if (!_strnicmp("all",&requestFileName[nbnLen+2],3) || + !_strnicmp("*.",&requestFileName[nbnLen+2],2)) + { + found = 1; + strcpy(referralPath, requestFileName); + refLen = reqLen; + } else { + userp = smb_GetTran2User(vcp, p); + if (!userp) { + osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid); + code = CM_ERROR_BADSMB; + goto done; + } + + /* + * We have a requested path. Check to see if it is something + * we know about. + */ + code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2], + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + userp, NULL, &req, &scp); + if (code == 0) { + /* Yes it is. */ + found = 1; + strcpy(referralPath, requestFileName); + refLen = reqLen; + } else if (code == CM_ERROR_PATH_NOT_COVERED ) { + char temp[1024]; + char pathName[1024]; + char *lastComponent; + /* + * we have a msdfs link somewhere in the path + * we should figure out where in the path the link is. + * and return it. + */ + osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral PATH_NOT_COVERED [%s]", requestFileName); + + strcpy(temp, &requestFileName[nbnLen+2]); + + do { + if (dscp) { + cm_ReleaseSCache(dscp); + dscp = 0; + } + if (scp) { + cm_ReleaseSCache(scp); + scp = 0; + } + smb_StripLastComponent(pathName, &lastComponent, temp); + + code = cm_NameI(cm_data.rootSCachep, pathName, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + userp, NULL, &req, &dscp); + if (code == 0) { + code = cm_NameI(dscp, ++lastComponent, + CM_FLAG_CASEFOLD, + userp, NULL, &req, &scp); + if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) + break; + } + } while (code == CM_ERROR_PATH_NOT_COVERED); + + /* scp should now be the DfsLink we are looking for */ + if (scp) { + /* figure out how much of the input path was used */ + reqLen = nbnLen+2 + strlen(pathName) + 1 + strlen(lastComponent); + + strcpy(referralPath, &scp->mountPointStringp[strlen("msdfs:")]); + refLen = strlen(referralPath); + found = 1; + } + } else { + char shareName[MAX_PATH + 1]; + char *p, *q; + /* we may have a sharename that is a volume reference */ + + for (p = &requestFileName[nbnLen+2], q = shareName; *p && *p != '\\'; p++, q++) + { + *q = *p; + } + *q = '\0'; + + if (smb_FindShare(vcp, vcp->usersp, shareName, &p)) { + code = cm_NameI(cm_data.rootSCachep, "", + CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, + userp, p, &req, &scp); + free(p); + + if (code == 0) { + found = 1; + strcpy(referralPath, requestFileName); + refLen = reqLen; + } + } + } + } + + if (found) + { + USHORT * sp; + struct smb_v2_referral * v2ref; + outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (refLen + 8)); + + sp = (USHORT *)outp->datap; + idx = 0; + sp[idx++] = reqLen; /* path consumed */ + sp[idx++] = 1; /* number of referrals */ + sp[idx++] = 0x03; /* flags */ #ifdef DFS_VERSION_1 - sp[idx++] = 1; /* Version Number */ - sp[idx++] = reqLen + 4; /* Referral Size */ - sp[idx++] = 1; /* Type = SMB Server */ - sp[idx++] = 0; /* Do not strip path consumed */ - for ( i=0;i<=reqLen; i++ ) - sp[i+idx] = requestFileName[i]; + sp[idx++] = 1; /* Version Number */ + sp[idx++] = refLen + 4; /* Referral Size */ + sp[idx++] = 1; /* Type = SMB Server */ + sp[idx++] = 0; /* Do not strip path consumed */ + for ( i=0;i<=refLen; i++ ) + sp[i+idx] = referralPath[i]; #else /* DFS_VERSION_2 */ - sp[idx++] = 2; /* Version Number */ - sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */ - idx += (sizeof(struct smb_v2_referral) / 2); - v2ref = (struct smb_v2_referral *) &sp[5]; - v2ref->ServerType = 1; /* SMB Server */ - v2ref->ReferralFlags = 0x03; - v2ref->Proximity = 0; /* closest */ - v2ref->TimeToLive = 3600; /* seconds */ - v2ref->DfsPathOffset = idx * 2; - v2ref->DfsAlternativePathOffset = idx * 2; - v2ref->NetworkAddressOffset = 0; - for ( i=0;i<=reqLen; i++ ) - sp[i+idx] = requestFileName[i]; + sp[idx++] = 2; /* Version Number */ + sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */ + idx += (sizeof(struct smb_v2_referral) / 2); + v2ref = (struct smb_v2_referral *) &sp[5]; + v2ref->ServerType = 1; /* SMB Server */ + v2ref->ReferralFlags = 0x03; + v2ref->Proximity = 0; /* closest */ + v2ref->TimeToLive = 3600; /* seconds */ + v2ref->DfsPathOffset = idx * 2; + v2ref->DfsAlternativePathOffset = idx * 2; + v2ref->NetworkAddressOffset = 0; + for ( i=0;i<=refLen; i++ ) + sp[i+idx] = referralPath[i]; #endif + } } else { - userp = smb_GetTran2User(vcp, p); - if (!userp) { - osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid); - code = CM_ERROR_BADSMB; - goto done; - } - - /* not done yet */ code = CM_ERROR_NOSUCHPATH; } - + done: + if (dscp) + cm_ReleaseSCache(dscp); + if (scp) + cm_ReleaseSCache(scp); if (userp) cm_ReleaseUser(userp); if (code == 0) @@ -3679,10 +3795,11 @@ smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_ return CM_ERROR_BADOP; } -long -smb_ApplyV3DirListPatches(cm_scache_t *dscp, - smb_dirListPatch_t **dirPatchespp, int infoLevel, cm_user_t *userp, - cm_req_t *reqp) +static long +smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, + char * tidPathp, char * relPathp, + int infoLevel, cm_user_t *userp, + cm_req_t *reqp) { long code = 0; cm_scache_t *scp; @@ -3697,6 +3814,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t *npatchp; afs_uint32 rights; afs_int32 mustFake = 0; + char path[AFSPATHMAX]; code = cm_FindACLCache(dscp, userp, &rights); if (code == 0 && !(rights & PRSFS_READ)) @@ -3716,7 +3834,12 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, for(patchp = *dirPatchespp; patchp; patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) { + snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name); + reqp->relPathp = path; + reqp->tidPathp = tidPathp; + code = cm_GetSCache(&patchp->fid, &scp, userp, reqp); + reqp->relPathp = reqp->tidPathp = NULL; if (code) continue; @@ -3840,7 +3963,11 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, code = 0; while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { lock_ReleaseMutex(&scp->mx); + snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name); + reqp->relPathp = path; + reqp->tidPathp = tidPathp; code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, reqp); + reqp->relPathp = reqp->tidPathp = NULL; if (code == 0) { /* we have a more accurate file to use (the * target of the symbolic link). Otherwise, @@ -3884,7 +4011,8 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, /* Copy attributes */ lattr = smb_ExtAttributes(scp); - if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK) { + if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK || + code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) { if (lattr == SMB_ATTR_NORMAL) lattr = SMB_ATTR_DIRECTORY; else @@ -4117,7 +4245,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op int attribute; long nextCookie; long code = 0, code2 = 0; - char *pathp; + char *pathp = 0; int maxCount; smb_dirListPatch_t *dirListPatchesp; smb_dirListPatch_t *curPatchp; @@ -4138,11 +4266,12 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op int searchFlags; int eos; smb_tran2Packet_t *outp; /* response packet */ - char *tidPathp; + char *tidPathp = 0; int align; char shortName[13]; /* 8.3 name if needed */ int NeedShortName; char *shortNameEnd; + cm_dirEntry_t * dep = NULL; cm_req_t req; char * s; @@ -4268,9 +4397,10 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op #ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(p) ) + if ( WANTS_DFS_PATHNAMES(p) || pnc ) code = CM_ERROR_PATH_NOT_COVERED; else code = CM_ERROR_BADSHARENAME; @@ -4461,7 +4591,11 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op curPatchp->fid.unique = targetscp->fid.unique; /* temp */ - curPatchp->dep = NULL; + dep = (cm_dirEntry_t *)malloc(sizeof(cm_dirEntry_t)+strlen(maskp)); + strcpy(dep->name, maskp); + dep->fid.vnode = targetscp->fid.vnode; + dep->fid.unique = targetscp->fid.unique; + curPatchp->dep = dep; } if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) { @@ -4480,7 +4614,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op } /* apply the patches */ - code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req); + code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, tidPathp, spacep->data, infoLevel, userp, &req); outp->parmsp[0] = 0; outp->parmsp[1] = 1; /* number of names returned */ @@ -4504,6 +4638,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op skip_file: smb_FreeTran2Packet(outp); + if (dep) + free(dep); cm_ReleaseSCache(scp); cm_ReleaseSCache(targetscp); cm_ReleaseUser(userp); @@ -4519,10 +4655,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t char *tp; long code = 0, code2 = 0; char *pathp; - cm_dirEntry_t *dep; + cm_dirEntry_t *dep = 0; int maxCount; - smb_dirListPatch_t *dirListPatchesp; - smb_dirListPatch_t *curPatchp; + smb_dirListPatch_t *dirListPatchesp = 0; + smb_dirListPatch_t *curPatchp = 0; cm_buf_t *bufferp; long temp; long orbytes; /* # of bytes in this output record */ @@ -4731,6 +4867,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t smb_ReleaseDirSearch(dsp); return 0; } + + strcpy(dsp->tidPath, tidPathp ? tidPathp : "/"); + strcpy(dsp->relPath, spacep->data); + code = cm_NameI(cm_data.rootSCachep, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); @@ -4739,9 +4879,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t if (code == 0) { #ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST if (scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(p) ) + if ( WANTS_DFS_PATHNAMES(p) || pnc ) code = CM_ERROR_PATH_NOT_COVERED; else code = CM_ERROR_BADSHARENAME; @@ -4877,9 +5018,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * of all of the status info for files in the dir. */ if (starPattern) { - smb_ApplyV3DirListPatches(scp, &dirListPatchesp, - infoLevel, userp, - &req); + code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, infoLevel, userp, &req); + lock_ObtainMutex(&scp->mx); if ((dsp->flags & SMB_DIRSEARCH_BULKST) && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) { @@ -5189,8 +5329,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t /* 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. */ - code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req); - + code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, + dsp->relPath, infoLevel, userp, &req); + /* now put out the final parameters */ if (returnedNames == 0) eos = 1; @@ -5393,9 +5534,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -5413,9 +5555,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -6579,12 +6722,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (code == 0) { #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -6612,12 +6756,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) userp, tidPathp, &req, &scp); #ifdef DFS_SUPPORT if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -6648,6 +6793,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #ifdef DFS_SUPPORT if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); if (scp) cm_ReleaseSCache(scp); cm_ReleaseSCache(dscp); @@ -6655,7 +6801,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -7378,12 +7524,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out if (code == 0) { #ifdef DFS_SUPPORT if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -7411,12 +7558,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out userp, tidPathp, &req, &scp); #ifdef DFS_SUPPORT if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME; @@ -7435,12 +7583,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out userp, tidPathp, &req, &dscp); #ifdef DFS_SUPPORT if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) { + int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); if (baseFidp) smb_ReleaseFID(baseFidp); - if ( WANTS_DFS_PATHNAMES(inp) ) + if ( WANTS_DFS_PATHNAMES(inp) || pnc ) return CM_ERROR_PATH_NOT_COVERED; else return CM_ERROR_BADSHARENAME;