Windows: Improve SMB detection of Local System account
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index a161f90..b25cc0c 100644 (file)
@@ -10,6 +10,7 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 #include <afs/cellconfig.h>
+#include <afs/afs_consts.h>
 #include <afs/ptserver.h>
 #include <ubik.h>
 
@@ -60,7 +61,8 @@ extern void afsi_log(char *pattern, ...);
 
 void cm_InitIoctl(void)
 {
-    lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
+    lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock",
+                          LOCK_HIERARCHY_AFSDBSBMT_GLOBAL);
 }
 
 /* 
@@ -73,7 +75,7 @@ cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 {
     long code;
 
-    code = buf_CleanVnode(scp, userp, reqp);
+    code = cm_FSync(scp, userp, reqp, FALSE);
     if (!code) {
         lock_ObtainWrite(&scp->rw);
         cm_DiscardSCache(scp);
@@ -94,15 +96,21 @@ cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
-       cm_noteLocalMountPointChange();
+       cm_noteLocalMountPointChange(FALSE);
        return 0;
     }
 #endif
 
     code = buf_FlushCleanPages(scp, userp, reqp);
         
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
+        lock_ObtainWrite(&scp->dirlock);
     lock_ObtainWrite(&scp->rw);
     cm_DiscardSCache(scp);
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+        cm_ResetSCacheDirectory(scp, 1);
+        lock_ReleaseWrite(&scp->dirlock);
+    }
     lock_ReleaseWrite(&scp->rw);
 
     osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
@@ -137,11 +145,11 @@ cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 vol
 {
     afs_int32 code = 0;
     cm_scache_t *scp;
-    int i;
+    unsigned int i;
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
-       cm_noteLocalMountPointChange();
+       cm_noteLocalMountPointChange(FALSE);
        return 0;
     }
 #endif
@@ -166,31 +174,6 @@ cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 vol
 }
 
 /*
- * Utility function.  Used within this file.
- * Invalidate ACL info for a user that has just        obtained or lost tokens.
- */
-void 
-cm_ResetACLCache(cm_user_t *userp)
-{
-    cm_scache_t *scp;
-    int hash;
-
-    lock_ObtainWrite(&cm_scacheLock);
-    for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
-        for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
-            cm_HoldSCacheNoLock(scp);
-            lock_ReleaseWrite(&cm_scacheLock);
-            lock_ObtainWrite(&scp->rw);
-            cm_InvalidateACLUser(scp, userp);
-            lock_ReleaseWrite(&scp->rw);
-            lock_ObtainWrite(&cm_scacheLock);
-            cm_ReleaseSCacheNoLock(scp);
-        }
-    }
-    lock_ReleaseWrite(&cm_scacheLock);
-}       
-
-/*
  *  TranslateExtendedChars - This is a fix for TR 54482.
  *
  *  If an extended character (80 - FF) is entered into a file
@@ -271,17 +254,17 @@ int cm_UnparseIoctlString(cm_ioctl_t *ioctlp,
 
     if ((ioctlp->flags & CM_IOCTLFLAG_USEUTF8) == CM_IOCTLFLAG_USEUTF8) {
         cchout = cm_ClientStringToUtf8(cstr, cchlen, outp,
-                                       SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp));
+                                       (int)(SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp)));
     } else {
         if (smb_StoreAnsiFilenames) {
             cchout = WideCharToMultiByte(CP_ACP, 0, cstr, cchlen,
                                          outp,
-                                         SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp),
+                                         (int)(SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp)),
                                          NULL, NULL);
         } else {
             cchout = WideCharToMultiByte(CP_OEMCP, 0, cstr, cchlen,
                                          outp,
-                                         SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp),
+                                         (int)(SMB_IOCTL_MAXDATA - (outp - ioctlp->outAllocp)),
                                          NULL, NULL);
         }
     }
@@ -299,7 +282,7 @@ int cm_UnparseIoctlString(cm_ioctl_t *ioctlp,
 cm_ioctlQueryOptions_t * 
 cm_IoctlGetQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp)
 {
-    afs_uint32 pathlen = strlen(ioctlp->inDatap) + 1;
+    afs_uint32 pathlen = (afs_uint32) strlen(ioctlp->inDatap) + 1;
     char *p = ioctlp->inDatap + pathlen;
     cm_ioctlQueryOptions_t * optionsp = NULL;
 
@@ -322,6 +305,7 @@ cm_IoctlSkipQueryOptions(struct cm_ioctl *ioctlp, struct cm_user *userp)
 {
     cm_ioctlQueryOptions_t * optionsp = (cm_ioctlQueryOptions_t *)ioctlp->inDatap;
     ioctlp->inDatap += optionsp->size;
+    ioctlp->inCopied -= optionsp->size;
 }
 
 /* format the specified path to look like "/afs/<cellname>/usr", by
@@ -343,7 +327,7 @@ cm_NormalizeAfsPath(clientchar_t *outpathp, long cchlen, clientchar_t *inpathp)
     if (!cm_ClientStrCmpNI(inpathp, cm_mountRootC, cm_mountRootCLen))
         cm_ClientStrCpy(outpathp, cchlen, inpathp);
     else if (!cm_ClientStrCmpNI(inpathp, bslash_mountRoot,
-                                cm_ClientStrLen(bslash_mountRoot)))
+                                (int)cm_ClientStrLen(bslash_mountRoot)))
         cm_ClientStrCpy(outpathp, cchlen, inpathp);
     else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
         cm_ClientStrPrintfN(outpathp, cchlen, _C("%s%s"), cm_mountRootC, inpathp);
@@ -390,7 +374,7 @@ void cm_NormalizeAfsPathAscii(char *outpathp, long outlen, char *inpathp)
         outpathp[strlen(outpathp)-1] = 0;
     }
 
-    if (!strcmpi (outpathp, cm_mountRoot)) {
+    if (!_stricmp (outpathp, cm_mountRoot)) {
         StringCbCopy(outpathp, outlen, cm_mountRoot);
     }
 }
@@ -414,6 +398,8 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
     int tlen;
     struct rx_connection * rxconnp;
 
+    memset(&volSync, 0, sizeof(volSync));
+
     /* now make the get acl call */
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
@@ -479,9 +465,13 @@ cm_IoctlGetFileCellName(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
             clientchar_t * cellname;
 
             cellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL); 
-            cm_UnparseIoctlString(ioctlp, NULL, cellname, -1);
-            free(cellname);
-            code = 0;
+            if (cellname == NULL) {
+                code = CM_ERROR_NOSUCHCELL;
+            } else {
+                cm_UnparseIoctlString(ioctlp, NULL, cellname, -1);
+                free(cellname);
+                code = 0;
+            }
         } else
             code = CM_ERROR_NOSUCHCELL;
     }
@@ -507,6 +497,8 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
     AFSFid fid;
     struct rx_connection * rxconnp;
 
+    memset(&volSync, 0, sizeof(volSync));
+
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
        code = CM_ERROR_NOACCESS;
@@ -550,7 +542,7 @@ cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_req_t
 {
     afs_int32 code;
     cm_scache_t *scp;
-    int i;
+    unsigned int i;
 
     lock_ObtainWrite(&cm_scacheLock);
     for (i=0; i<cm_data.scacheHashTableSize; i++) {
@@ -897,6 +889,84 @@ cm_IoctlGetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *sc
 
 
 /* 
+ * VIOC_SETOWNER internals.
+ * 
+ * Assumes that pioctl path has been parsed or skipped
+ * and that cm_ioctlQueryOptions_t have been parsed and skipped.
+ * 
+ * scp is held but not locked.
+ *
+ */
+afs_int32 
+cm_IoctlSetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
+{
+    afs_int32 code = 0;
+    char *cp;
+
+    lock_ObtainWrite(&scp->rw);
+    code = cm_SyncOp(scp, NULL, userp, reqp, 0,
+                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code == 0)
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    lock_ReleaseWrite(&scp->rw);
+
+    if (code == 0) {
+        afs_uint32 owner;
+        cm_attr_t attr;
+
+        memset(&attr, 0, sizeof(attr));
+
+        cp = ioctlp->inDatap;
+        memcpy((char *)&owner, cp, sizeof(afs_uint32));
+
+        attr.mask = CM_ATTRMASK_OWNER;
+        attr.owner = owner;
+
+        code = cm_SetAttr(scp, &attr, userp, reqp);
+    }
+    return code;
+}
+
+
+/* 
+ * VIOC_SETGROUP internals.
+ * 
+ * Assumes that pioctl path has been parsed or skipped
+ * and that cm_ioctlQueryOptions_t have been parsed and skipped.
+ * 
+ */
+afs_int32 
+cm_IoctlSetGroup(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
+{
+    afs_int32 code = 0;
+    char *cp;
+
+    lock_ObtainWrite(&scp->rw);
+    code = cm_SyncOp(scp, NULL, userp, reqp, 0,
+                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code == 0)
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    lock_ReleaseWrite(&scp->rw);
+
+    if (code == 0) {
+        afs_uint32 group;
+        cm_attr_t attr;
+
+        memset(&attr, 0, sizeof(attr));
+
+        cp = ioctlp->inDatap;
+        memcpy((char *)&group, cp, sizeof(afs_uint32));
+
+        attr.mask = CM_ATTRMASK_GROUP;
+        attr.group = group;
+
+        code = cm_SetAttr(scp, &attr, userp, reqp);
+    }
+    return code;
+}
+
+
+/* 
  * VIOCWHEREIS internals.
  * 
  * Assumes that pioctl path has been parsed or skipped.
@@ -905,7 +975,7 @@ cm_IoctlGetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *sc
 afs_int32 
 cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
 {
-    afs_int32 code;
+    afs_int32 code = 0;
     cm_cell_t *cellp;
     cm_volume_t *tvp;
     cm_serverRef_t **tsrpp, *current;
@@ -949,16 +1019,19 @@ cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp
        
         cp = ioctlp->outDatap;
         
-        tsrpp = cm_GetVolServers(tvp, volume);
-        lock_ObtainRead(&cm_serverLock);
-        for (current = *tsrpp; current; current = current->next) {
-            tsp = current->server;
-            memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
-            cp += sizeof(long);
+        tsrpp = cm_GetVolServers(tvp, volume, userp, reqp);
+        if (tsrpp == NULL) {
+            code = CM_ERROR_NOSUCHVOLUME;
+        } else {
+            lock_ObtainRead(&cm_serverLock);
+            for (current = *tsrpp; current; current = current->next) {
+                tsp = current->server;
+                memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
+                cp += sizeof(long);
+            }
+            lock_ReleaseRead(&cm_serverLock);
+            cm_FreeServerList(tsrpp, 0);
         }
-        lock_ReleaseRead(&cm_serverLock);
-        cm_FreeServerList(tsrpp, 0);
-
         /* still room for terminating NULL, add it on */
         volume = 0;    /* reuse vbl */
         memcpy(cp, (char *)&volume, sizeof(long));
@@ -967,7 +1040,7 @@ cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp
         ioctlp->outDatap = cp;
         cm_PutVolume(tvp);
     }
-    return 0;
+    return code;
 }       
 
 /* 
@@ -984,7 +1057,8 @@ cm_IoctlStatMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache
     clientchar_t *cp;
 
     cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
-    code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+
+    code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     if (code) 
         goto done_2;
 
@@ -1039,7 +1113,7 @@ cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
 
     cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
 
-    code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
         
     /* if something went wrong, bail out now */
     if (code)
@@ -1061,7 +1135,8 @@ cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
     lock_ReleaseWrite(&scp->rw);
 
 #ifdef USE_BPLUS
-    code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, &dirop);
+    code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ,
+                         CM_DIROP_FLAG_NONE, &dirop);
     if (code == 0) {
         code = cm_BPlusDirLookupOriginalName(&dirop, cp, &originalName);
         /* The cm_Dir* functions can't be used to lookup the
@@ -1372,8 +1447,12 @@ cm_IoctlGetCell(struct cm_ioctl *ioctlp, struct cm_user *userp)
         ioctlp->outDatap = basep + max * sizeof(afs_int32);
 
         cellnamep = cm_FsStringToClientStringAlloc(tcellp->name, -1, NULL);
-        cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
-        free(cellnamep);
+        if (cellnamep) {
+            cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
+            free(cellnamep);
+        } else {
+            tcellp = NULL;
+        }
     }
 
     if (tcellp) 
@@ -1406,44 +1485,137 @@ cm_IoctlNewCell(struct cm_ioctl *ioctlp, struct cm_user *userp)
     for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) 
     {
         afs_int32 code;
-       lock_ObtainMutex(&cp->mx);
+
         /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
         cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
-        cp->vlServersp = NULL;
+        lock_ReleaseWrite(&cm_cellLock);
+
         rock.cellp = cp;
         rock.flags = 0;
-        code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, &rock);
-#ifdef AFS_AFSDB_ENV
+        code = cm_SearchCellRegistry(1, cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
+        if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+            code = cm_SearchCellFileEx(cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
         if (code) {
             if (cm_dnsEnabled) {
                 int ttl;
                 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, &rock);
                 if ( code == 0 ) { /* got cell from DNS */
+                    lock_ObtainMutex(&cp->mx);
                     cp->flags |= CM_CELLFLAG_DNS;
                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                     cp->timeout = time(0) + ttl;
+                    lock_ReleaseMutex(&cp->mx);
                 }
             }
         } 
         else {
+            lock_ObtainMutex(&cp->mx);
             cp->flags &= ~CM_CELLFLAG_DNS;
+            lock_ReleaseMutex(&cp->mx);
         }
-#endif /* AFS_AFSDB_ENV */
         if (code) {
+            lock_ObtainMutex(&cp->mx);
             cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+            lock_ReleaseMutex(&cp->mx);
+            lock_ObtainWrite(&cm_cellLock);
         }
         else {
+            lock_ObtainMutex(&cp->mx);
             cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
+            lock_ReleaseMutex(&cp->mx);
+            lock_ObtainWrite(&cm_cellLock);
             cm_RandomizeServer(&cp->vlServersp);
         }
-       lock_ReleaseMutex(&cp->mx);
     }
-    
     lock_ReleaseWrite(&cm_cellLock);
     return 0;       
 }
 
 /* 
+ * VIOCNEWCELL2 internals.
+ *
+ * Assumes that pioctl path has been parsed or skipped.
+ *
+ * The pioctl data buffer consists of the following structure:
+ *
+ *  afs_uint32 flags
+ *  afs_uint32 alternative fs port
+ *  afs_uint32 alternative vl port
+ *  afs_uint32 count of vldb servers
+ *  char[]     cellname
+ *  char[]     linkedcell
+ *  n * char[] hostnames
+ */
+afs_int32
+cm_IoctlNewCell2(struct cm_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_uint32  code = 0;
+    afs_uint32  flags = 0;
+    afs_uint32  fsport = 0;
+    afs_uint32  vlport = 0;
+    afs_uint32  i, host_count = 0;
+    char *      cellname = NULL;
+    char *      linked_cellname = NULL;
+    char *tp;
+    size_t tplen;
+    afs_uint32 *lp;
+    char * hostname[AFS_MAXHOSTS];
+    size_t len;
+
+    memset(hostname, 0, sizeof(hostname));
+
+    tp = ioctlp->inDatap;
+    tplen = ioctlp->inCopied;
+    lp = (afs_uint32 *)tp;
+
+    if (tplen >= 4 * sizeof(afs_uint32)) {
+        flags = *lp++;
+        fsport = *lp++;
+        vlport = *lp++;
+        host_count = *lp++;
+        tp = (char *)lp;
+        tplen -= 4 * sizeof(afs_uint32);
+    }
+
+    if ( FAILED(StringCbLength(tp, tplen, &len)) ||
+         len + 1 > CELL_MAXNAMELEN)
+        return CM_ERROR_INVAL;
+    cellname = tp;
+    tp += len + 1;
+    tplen -= (len + 1);
+
+    if ( FAILED(StringCbLength(tp, tplen, &len)) ||
+         len + 1 > CELL_MAXNAMELEN)
+        return CM_ERROR_INVAL;
+    linked_cellname = tp;
+    tp += len + 1;
+    tplen -= (len + 1);
+
+    if (!(flags & VIOC_NEWCELL2_FLAG_USEDNS)) {
+        for ( i=0; i<host_count; i++) {
+            if ( FAILED(StringCbLength(tp, tplen, &len)) )
+                return CM_ERROR_INVAL;
+            hostname[i] = tp;
+            tp += len + 1;
+            tplen -= (len + 1);
+        }
+    }
+
+    code = cm_CreateCellWithInfo( cellname, linked_cellname,
+                                  vlport, host_count,
+                                  hostname,
+                                  (flags & VIOC_NEWCELL2_FLAG_USEDNS) ? CM_CELLFLAG_DNS : 0);
+
+    if (code == 0 && (flags & VIOC_NEWCELL2_FLAG_USEREG)) {
+        cm_AddCellToRegistry( cellname, linked_cellname,
+                              vlport, host_count,
+                              hostname,
+                              (flags & VIOC_NEWCELL2_FLAG_USEDNS) ? CM_CELLFLAG_DNS : 0);
+    }
+    return code;
+}
+
+/*
  * VIOC_GET_WS_CELL internals.
  * 
  * Assumes that pioctl path has been parsed or skipped.
@@ -1460,8 +1632,12 @@ cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp)
     } else if (cm_data.rootCellp) {
         clientchar_t * cellnamep = cm_FsStringToClientStringAlloc(cm_data.rootCellp->name, -1, NULL);
         /* return the default cellname to the caller */
-        cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
-        free(cellnamep);
+        if (cellnamep) {
+            cm_UnparseIoctlString(ioctlp, NULL, cellnamep, -1);
+            free(cellnamep);
+        } else {
+            code = CM_ERROR_NOSUCHCELL;
+        }
     } else {
         /* if we don't know our default cell, return failure */
         code = CM_ERROR_NOSUCHCELL;
@@ -1481,7 +1657,8 @@ cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp)
     afs_uint32 setSysName;
     char *cp, *cp2;
     clientchar_t *inname = NULL;
-    int t, count;
+    int t;
+    unsigned int count;
 
     memcpy(&setSysName, ioctlp->inDatap, sizeof(afs_uint32));
     ioctlp->inDatap += sizeof(afs_uint32);
@@ -1537,7 +1714,7 @@ cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp)
         }
         cm_sysNameCount = setSysName;
     } else {
-        afs_int32 i32;
+        afs_uint32 i32;
 
         /* return the sysname to the caller */
         i32 = cm_sysNameCount;
@@ -1660,35 +1837,50 @@ cm_IoctlSetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
         srvin          = &(spin->servers[i]);
         rank           = srvin->rank + (rand() & 0x000f);
         tmp.sin_addr   = srvin->host;
+        switch (type) {
+        case CM_SERVER_VLDB:
+            tmp.sin_port = htons(7003);
+            break;
+        case CM_SERVER_FILE:
+            tmp.sin_port = htons(7000);
+            break;
+        }
         tmp.sin_family = AF_INET;
 
         tsp = cm_FindServer(&tmp, type);
         if ( tsp )             /* an existing server - ref count increased */
         {
-            tsp->ipRank = rank; /* no need to protect by mutex*/
-
-            if (type == CM_SERVER_FILE)
-            {   /* fileserver */
-                /* find volumes which might have RO copy 
-                /* on server and change the ordering of 
+            lock_ObtainMutex(&tsp->mx);
+            tsp->ipRank = rank;
+            tsp->flags |= CM_SERVERFLAG_PREF_SET;
+           tsp->adminRank = tsp->ipRank;
+            lock_ReleaseMutex(&tsp->mx);
+
+            switch (type) {
+            case CM_SERVER_FILE:
+                /*
+                 * find volumes which might have RO copy
+                 * on server and change the ordering of 
                  * their RO list 
                  */
                 cm_ChangeRankVolume(tsp);
-            }
-            else       
-            {
+                break;
+            case CM_SERVER_VLDB:
                 /* set preferences for an existing vlserver */
                 cm_ChangeRankCellVLServer(tsp);
+                break;
             }
         }
         else   /* add a new server without a cell */
         {
-            tsp = cm_NewServer(&tmp, type, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
+            tsp = cm_NewServer(&tmp, type, NULL, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
+            lock_ObtainMutex(&tsp->mx);
+            tsp->ipRank = rank;
+            tsp->flags |= CM_SERVERFLAG_PREF_SET;
+           tsp->adminRank = tsp->ipRank;
+            lock_ReleaseMutex(&tsp->mx);
             tsp->ipRank = rank;
         }
-       lock_ObtainMutex(&tsp->mx);
-       tsp->flags |= CM_SERVERFLAG_PREF_SET;
-       lock_ReleaseMutex(&tsp->mx);
        cm_PutServer(tsp);  /* decrease refcount */
     }
     return 0;
@@ -1722,9 +1914,9 @@ cm_IoctlGetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
             continue;    /* catch up to where we left off */
         }
 
-        if ( vlonly && (tsp->type == CM_SERVER_FILE) )
+        if ( vlonly && (tsp->type != CM_SERVER_VLDB) )
             continue;   /* ignore fileserver for -vlserver option*/
-        if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
+        if ( !vlonly && (tsp->type != CM_SERVER_FILE) )
             continue;   /* ignore vlservers */
 
         srvout->host = tsp->addr.sin_addr;
@@ -1943,7 +2135,7 @@ cm_IoctlListlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *ds
     cp = ioctlp->inDatap;
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
     if (code) 
         return code;
@@ -2013,7 +2205,7 @@ cm_IoctlIslink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp
     osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
     if (code)
         return code;
@@ -2050,7 +2242,7 @@ cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *
     cp = ioctlp->inDatap;
 
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
-    code = cm_Lookup(dscp, clientp, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
 
     /* if something went wrong, bail out now */
     if (code)
@@ -2074,7 +2266,8 @@ cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *
     lock_ReleaseWrite(&scp->rw);
         
 #ifdef USE_BPLUS
-    code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, &dirop);
+    code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ,
+                         CM_DIROP_FLAG_NONE, &dirop);
     if (code == 0) {
         code = cm_BPlusDirLookupOriginalName(&dirop, clientp, &originalName);
         /* cm_Dir*() functions can't be used to lookup the original
@@ -2153,6 +2346,7 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
     int i;
     char * p, * r;
 
+    memset(&info, 0, sizeof(info));
     tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
     code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
     afsconf_Close(tdir);
@@ -2178,6 +2372,8 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
 
     code = ubik_ClientInit(serverconns, &pruclient);
     if (code) {
+        if (info.linkedCell)
+            free(info.linkedCell);
        return code;
     }
 
@@ -2211,6 +2407,8 @@ cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
        pruclient = NULL;
     }
 
+    if (info.linkedCell)
+        free(info.linkedCell);
     return 0;
 }
 #endif /* QUERY_AFSID */
@@ -2345,7 +2543,7 @@ cm_IoctlSetToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
         ioctlp->flags |= CM_IOCTLFLAG_LOGON;
     }
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(cellp, userp);
 
     if (release_userp)
        cm_ReleaseUser(userp);
@@ -2520,7 +2718,7 @@ cm_IoctlGetToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ReleaseMutex(&userp->mx);
 
-    cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
+    cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data, NULL);
 
     return 0;
 }
@@ -2568,7 +2766,7 @@ cm_IoctlDelToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ReleaseMutex(&userp->mx);
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(cellp, userp);
 
     return 0;
 }
@@ -2603,7 +2801,7 @@ cm_IoctlDelAllToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ReleaseMutex(&userp->mx);
 
-    cm_ResetACLCache(userp);
+    cm_ResetACLCache(NULL, userp);
 
     return 0;
 }
@@ -2810,8 +3008,10 @@ cm_IoctlSetRxkcrypt(cm_ioctl_t *ioctlp, cm_user_t *userp)
     memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
 
     if (c != cryptall) {
-       if (cryptall)
+       if (cryptall == 1)
             LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+       else if (cryptall == 2)
+            LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_AUTH);
        else
             LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
     }
@@ -3005,7 +3205,10 @@ cm_IoctlMemoryDump(struct cm_ioctl *ioctlp, struct cm_user *userp)
     cm_DumpVolumes(hLogFile, cookie, 1);
     cm_DumpSCache(hLogFile, cookie, 1);
     cm_DumpBufHashTable(hLogFile, cookie, 1);
+    cm_DumpServers(hLogFile, cookie, 1);
     smb_DumpVCP(hLogFile, cookie, 1);
+    rx_DumpCalls(hLogFile, cookie);
+    rx_DumpPackets(hLogFile, cookie);
 
     CloseHandle(hLogFile);                          
   
@@ -3032,6 +3235,8 @@ cm_CheckServersStatus(cm_serverRef_t *serversp)
 
     lock_ObtainRead(&cm_serverLock);
     for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+        if (tsrp->status == srv_deleted)
+            continue;
         if (tsp = tsrp->server) {
             cm_GetServerNoLock(tsp);
             lock_ReleaseRead(&cm_serverLock);