From 36bdf1ccd859fb0039d8ae9abd04f9eea08d704d Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 28 Jan 2008 07:22:32 +0000 Subject: [PATCH] windows-freelance-improved-dfs-handling-20080127 LICENSE MIT Cell names are published as share names. As a result they are searched for as part of the Dfs Referral evaluation. If share "foo" can not be reached, the CIFS client will fallback to searching for "fo" as well. Since the freelance client automatically adds a symlink for prefixes of the cell name, this results in both "foo" and "fo" being added to the freelance root.afs volume. This patch prevents that negative side effect. --- src/WINNT/afsd/cm.h | 1 + src/WINNT/afsd/cm_freelance.c | 22 ++++++++++++++++------ src/WINNT/afsd/cm_freelance.h | 2 ++ src/WINNT/afsd/cm_vnodeops.c | 20 ++++++++++++++------ src/WINNT/afsd/smb3.c | 10 +++++++--- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index 09dc570f6..4f327b5cc 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -242,6 +242,7 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_FLAG_DIRSEARCH 0x40 /* for directory search */ #define CM_FLAG_CHECKPATH 0x80 /* Path instead of File */ #define CM_FLAG_NOPROBE 0x100 /* For use with cm_GetCellxxx - do not probe server status */ +#define CM_FLAG_DFS_REFERRAL 0x200 /* The request is a DFS Referral - the last char of the lookup name may be missing */ /* error codes */ #define CM_ERROR_BASE 0x66543200 diff --git a/src/WINNT/afsd/cm_freelance.c b/src/WINNT/afsd/cm_freelance.c index a7646f999..068eb8736 100644 --- a/src/WINNT/afsd/cm_freelance.c +++ b/src/WINNT/afsd/cm_freelance.c @@ -794,7 +794,7 @@ int cm_getNoLocalMountPoints() { return cm_noLocalMountPoints; } -long cm_FreelanceMountPointExists(char * filename) +long cm_FreelanceMountPointExists(char * filename, int prefix_ok) { char* cp; char line[512]; @@ -862,6 +862,11 @@ long cm_FreelanceMountPointExists(char * filename) found = 1; break; } + + if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) { + found = 1; + break; + } } RegCloseKey(hkFreelance); } @@ -871,7 +876,7 @@ long cm_FreelanceMountPointExists(char * filename) return found; } -long cm_FreelanceSymlinkExists(char * filename) +long cm_FreelanceSymlinkExists(char * filename, int prefix_ok) { char* cp; char line[512]; @@ -919,6 +924,11 @@ long cm_FreelanceSymlinkExists(char * filename) found = 1; break; } + + if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) { + found = 1; + break; + } } for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) { TCHAR szValueName[16]; @@ -978,8 +988,8 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, return -1; } - if ( cm_FreelanceMountPointExists(filename) || - cm_FreelanceSymlinkExists(filename) ) + if ( cm_FreelanceMountPointExists(filename, 0) || + cm_FreelanceSymlinkExists(filename, 0) ) return -1; osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s", @@ -1205,8 +1215,8 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp) return CM_ERROR_EXISTS; } - if ( cm_FreelanceMountPointExists(filename) || - cm_FreelanceSymlinkExists(filename) ) + if ( cm_FreelanceMountPointExists(filename, 0) || + cm_FreelanceSymlinkExists(filename, 0) ) return CM_ERROR_EXISTS; lock_ObtainMutex(&cm_Freelance_Lock); diff --git a/src/WINNT/afsd/cm_freelance.h b/src/WINNT/afsd/cm_freelance.h index 2cebe493e..9f327fab8 100644 --- a/src/WINNT/afsd/cm_freelance.h +++ b/src/WINNT/afsd/cm_freelance.h @@ -19,6 +19,8 @@ extern long cm_FreelanceRemoveMount(char *toremove); extern long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp); extern long cm_FreelanceRemoveSymlink(char *toremove); extern long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp); +extern long cm_FreelanceMountPointExists(char * filename, int prefix_ok); +extern long cm_FreelanceSymlinkExists(char * filename, int prefix_ok); extern int cm_clearLocalMountPointChange(); extern int cm_FakeRootFid(cm_fid_t *fidp); diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 67665c594..b1b00e0a9 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -1288,21 +1288,29 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %s", osi_LogSaveString(afsd_logp,namep)); + + /* + * There is an ugly behavior where a share name "foo" will be searched + * for as "fo". If the searched for name differs by an already existing + * symlink or mount point in the Freelance directory, do not add the + * new value automatically. + */ + if (namep[0] == '.') { if (cm_GetCell_Gen(&namep[1], &fullname[1], CM_FLAG_CREATE)) { found = 1; - if ( stricmp(&namep[1], &fullname[1]) ) + if (!cm_FreelanceMountPointExists(fullname, 0)) + code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.", 1, &rock.fid); + if ( stricmp(&namep[1], &fullname[1]) && !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0)) code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid); - else - code = cm_FreelanceAddMount(namep, &fullname[1], "root.cell.", 1, &rock.fid); } } else { if (cm_GetCell_Gen(namep, fullname, CM_FLAG_CREATE)) { found = 1; - if ( stricmp(namep, fullname) ) + if (!cm_FreelanceMountPointExists(fullname, 0)) + code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid); + if ( stricmp(namep, fullname) && !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0)) code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid); - else - code = cm_FreelanceAddMount(namep, fullname, "root.cell.", 0, &rock.fid); } } if (!found || code < 0) { /* add mount point failed, so give up */ diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index fbb0cc337..f2caff291 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -168,7 +168,7 @@ void OutputDebugHexDump(unsigned char * buffer, int len) { for (i=0;i32 && k<127)?k:'.'; } if(i) { - osi_Log0(smb_logp, "%s", osi_LogSaveString(smb_logp, buf)); + osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf)); strcat(buf,"\r\n"); OutputDebugString(buf); } @@ -3634,9 +3634,13 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t /* * We have a requested path. Check to see if it is something * we know about. + * + * But be careful because the name that we might be searching + * for might be a known name with the final character stripped + * off. If we */ code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2], - CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL, userp, NULL, &req, &scp); if (code == 0) { /* Yes it is. */ -- 2.39.5