integrated-logon-20040323
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index 2de6df1..9138bb1 100644 (file)
@@ -30,7 +30,7 @@
 #include "smb.h"
 
 #ifndef DJGPP
-#include <rxkad.h>
+#include <rx/rxkad.h>
 #include "afsrpc.h"
 #else
 #include <rx/rxkad.h>
 
 #include "cm_rpc.h"
 
+#ifdef _DEBUG
+#include <crtdbg.h>
+#endif
+
 /* Copied from afs_tokens.h */
 #define PIOCTL_LOGON   0x1
 #define MAX_PATH 260
@@ -109,16 +113,18 @@ void cm_ResetACLCache(cm_user_t *userp)
  */
 void TranslateExtendedChars(char *str)
 {
-  char *p;
-  
-        if (!str || !*str)
-                return;
+#ifdef DJGPP
+    char *p;
+#endif
+
+    if (!str || !*str)
+        return;
 
 #ifndef DJGPP
-        CharToOem(str, str);
+    CharToOem(str, str);
 #else
-        p = str;
-        while (*p) *p++ &= 0x7f;  /* turn off high bit; probably not right */
+    p = str;
+    while (*p) *p++ &= 0x7f;  /* turn off high bit; probably not right */
 #endif
 }
         
@@ -173,15 +179,19 @@ void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
 void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
 {
        char *cp;
-
-       if (!strnicmp (inpathp, "/afs", strlen("/afs")))
+    char bslash_mountRoot[256];
+       
+    strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
+    bslash_mountRoot[0] = '\\';
+       
+    if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
                lstrcpy (outpathp, inpathp);
-       else if (!strnicmp (inpathp, "\\afs", strlen("\\afs")))
+       else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
                lstrcpy (outpathp, inpathp);
        else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
-               sprintf (outpathp, "/afs%s", inpathp);
+               sprintf (outpathp, "%s%s", cm_mountRoot, inpathp);
        else // inpathp looks like "<cell>/usr"
-               sprintf (outpathp, "/afs/%s", inpathp);
+               sprintf (outpathp, "%s/%s", cm_mountRoot, inpathp);
 
        for (cp = outpathp; *cp != 0; ++cp) {
                if (*cp == '\\')
@@ -192,8 +202,8 @@ void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
            outpathp[strlen(outpathp)-1] = 0;
        }
 
-       if (!strcmpi (outpathp, "/afs")) {
-           strcpy (outpathp, "/afs/");
+       if (!strcmpi (outpathp, cm_mountRoot)) {
+        strcpy (outpathp, cm_mountRoot);
        }
 }
 
@@ -915,12 +925,35 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
        else return CM_ERROR_NOMORETOKENS;      /* mapped to EDOM */
 }
 
+extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
+
 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-       /* don't need to do, since NT cache manager will re-read afsdcell.ini
-         * on every access to a new cell.
-         */
-       return CM_ERROR_INVAL;
+    /* NT cache manager will read cell information from afsdcell.ini each time
+     * cell is accessed. So, this call is necessary only if list of server for a cell 
+     * changes (or IP addresses of cell servers changes).
+     * All that needs to be done is to refresh server information for all cells that 
+     * are already loaded.
+  
+     * cell list will be cm_CellLock and cm_ServerLock will be held for write.
+    */  
+  
+    cm_cell_t *tcellp;
+  
+    cm_SkipIoctlPath(ioctlp);
+    lock_ObtainWrite(&cm_cellLock);
+  
+    for(tcellp = cm_allCellsp; tcellp; tcellp=tcellp->nextp) 
+    {
+        /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
+        cm_FreeServerList(&tcellp->vlServersp);
+        tcellp->vlServersp = NULL;
+        cm_SearchCellFile(tcellp->namep, tcellp->namep, cm_AddCellProc, tcellp);
+        cm_RandomizeServer(&tcellp->vlServersp);
+    }
+    
+    lock_ReleaseWrite(&cm_cellLock);
+    return 0;       
 }
 
 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
@@ -1027,7 +1060,8 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
        vlonly     = spin->flags;
        if ( vlonly )
                type = CM_SERVER_VLDB;
-       else    type = CM_SERVER_FILE;
+       else    
+        type = CM_SERVER_FILE;
 
        for ( i=0; i < noServers; i++) 
        {
@@ -1037,7 +1071,7 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                tmp.sin_family = AF_INET;
 
                tsp = cm_FindServer(&tmp, type);
-               if ( tsp )              /* an existing server */
+               if ( tsp )              /* an existing server - ref count increased */
                {
                        tsp->ipRank = rank; /* no need to protect by mutex*/
 
@@ -1053,13 +1087,13 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                            /* set preferences for an existing vlserver */
                            cm_ChangeRankCellVLServer(tsp);
                        }
+            cm_PutServer(tsp);  /* decrease refcount */
                }
-               else                    /* add a new server without a cell*/
+               else    /* add a new server without a cell */
                {
-                       tsp = cm_NewServer(&tmp, type, NULL);
+                       tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
                        tsp->ipRank = rank;
                }
-               cm_PutServer(tsp);
        }
        return 0;
 }
@@ -1121,65 +1155,77 @@ long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
        char leaf[256];
-        long code;
-        cm_scache_t *dscp;
-        cm_attr_t tattr;
-        char *cp;
+    long code;
+    cm_scache_t *dscp;
+    cm_attr_t tattr;
+    char *cp;
        cm_req_t req;
-        char mpInfo[256];
-        char fullCell[256];
+    char mpInfo[256];
+    char fullCell[256];
        char volume[256];
        char cell[256];
+       int ttl;
 
        cm_InitReq(&req);
         
-        code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
-        if (code) return code;
+    code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
+    if (code) return code;
 
-        /* Translate chars for the mount point name */
-        TranslateExtendedChars(leaf);
+    /* Translate chars for the mount point name */
+    TranslateExtendedChars(leaf);
 
-        /* 
-         * The fs command allows the user to specify partial cell names on NT.  These must
-         * be expanded to the full cell name for mount points so that the mount points will
-         * work on UNIX clients.
-         */
+    /* 
+     * The fs command allows the user to specify partial cell names on NT.  These must
+     * be expanded to the full cell name for mount points so that the mount points will
+     * work on UNIX clients.
+     */
 
        /* Extract the possibly partial cell name */
        strcpy(cell, ioctlp->inDatap + 1);      /* Skip the mp type character */
         
-        if (cp = strchr(cell, ':')) {
+    if (cp = strchr(cell, ':')) {
                /* Extract the volume name */
-               *cp = 0;
+        *cp = 0;
                strcpy(volume,  cp + 1);
        
-               /* Get the full name for this cell */
-               code = cm_SearchCellFile(cell, fullCell, 0, 0);
-               if (code)
+        /* Get the full name for this cell */
+        code = cm_SearchCellFile(cell, fullCell, 0, 0);
+#ifdef AFS_AFSDB_ENV
+               if (code && cm_dnsEnabled)
+            code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
+#endif
+        if (code)
                        return CM_ERROR_NOSUCHCELL;
        
-               sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
+        sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
        } else {
-               /* No cell name specified */
-               strcpy(mpInfo, ioctlp->inDatap);
-        }
-
+        /* No cell name specified */
+        strcpy(mpInfo, ioctlp->inDatap);
+    }
+
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
+         /* we are adding the mount point to the root dir., so call
+            the freelance code to do the add. */
+         code = cm_FreelanceAddMount(leaf, fullCell, volume, NULL);
+         return code;
+       }
+#endif
        /* create the symlink with mode 644.  The lack of X bits tells
-         * us that it is a mount point.
-         */
+     * us that it is a mount point.
+     */
        tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
-        tattr.unixModeBits = 0644;
+    tattr.unixModeBits = 0644;
        tattr.clientModTime = time(NULL);
 
-        code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
+    code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                dscp, leaf, NULL, TRUE);
-
-        cm_ReleaseSCache(dscp);
+                         FILE_NOTIFY_CHANGE_DIR_NAME,
+                         dscp, leaf, NULL, TRUE);
 
-        return code;
+    cm_ReleaseSCache(dscp);
+    return code;
 }
 
 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
@@ -1256,7 +1302,8 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
        if (code == 0) {
                cp = ioctlp->outDatap;
                if (newRootScp != NULL) {
-                       strcpy(cp, "/afs/");
+            strcpy(cp, cm_mountRoot);
+            strcat(cp, "/");
                        cp += strlen(cp);
                }
                strcpy(cp, spacep->data);
@@ -1270,6 +1317,33 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
        return code;
 }
 
+long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{/*CHECK FOR VALID SYMLINK*/
+       long code;
+       cm_scache_t *dscp;
+       cm_scache_t *scp;
+       char *cp;
+       cm_req_t req;
+
+       cm_InitReq(&req);
+
+       code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
+       if (code) return code;
+
+       cp = ioctlp->inDatap;
+       osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
+
+       code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
+       cm_ReleaseSCache(dscp);
+       if (code) return code;
+
+       /* Check that it's a real symlink */
+       if (scp->fileType != CM_SCACHETYPE_SYMLINK)
+               code = CM_ERROR_INVAL;
+       cm_ReleaseSCache(scp);
+       return code;
+}
+
 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
        long code;
@@ -1340,6 +1414,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        afs_uuid_t uuid;
        int flags;
        char sessionKey[8];
+       char *smbname;
 
        saveDataPtr = ioctlp->inDatap;
 
@@ -1384,6 +1459,13 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
                uname = tp;
                tp += strlen(tp) + 1;
 
+        if (flags & PIOCTL_LOGON) {
+                 /* SMB user name with which to associate tokens */
+                 smbname = tp;
+                 fprintf(stderr, "SMB name = %s\n", smbname);
+                 tp += strlen(tp) + 1;
+        }
+
 #ifndef DJGPP   /* for win95, session key is back in pioctl */
                /* uuid */
                memcpy(&uuid, tp, sizeof(uuid));
@@ -1393,6 +1475,10 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        } else
                cellp = cm_rootCellp;
 
+       if (flags & PIOCTL_LOGON) {
+          userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
+       }
+       
        /* store the token */
        lock_ObtainMutex(&userp->mx);
        ucellp = cm_GetUCell(userp, cellp);
@@ -1707,7 +1793,9 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
                         * leading "/afs" when writing out the submount.
                         */
                        WritePrivateProfileString("AFS Submounts",
-                                       submountreqp, &afspath[strlen("/afs")],
+                                       submountreqp, 
+                                       (strlen(&afspath[strlen(cm_mountRoot)])) ?
+                                                 &afspath[strlen(cm_mountRoot)]:"/",
                                        "afsdsbmt.ini");
 
                        strcpy(ioctlp->outDatap, submountreqp);
@@ -1820,8 +1908,9 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
        sprintf(ioctlp->outDatap, "auto%ld", nextAutoSubmount);
 
        WritePrivateProfileString("AFS Submounts", ioctlp->outDatap,
-                                       &afspath[lstrlen("/afs")],
-                                       "afsdsbmt.ini");
+                                 (strlen(&afspath[lstrlen(cm_mountRoot)])) ? 
+                                 &afspath[lstrlen(cm_mountRoot)]:"/",
+                                 "afsdsbmt.ini");
 
        ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
        lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
@@ -1849,9 +1938,88 @@ long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
 extern int afsd_shutdown(int);
 extern int afs_shutdown;
 
-long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp)
-{
+long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
   afs_shutdown = 1;   /* flag to shut down */
   return 0;
 }
 #endif /* DJGPP */
+
+long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
+{
+  smb_user_t *uidp = ioctlp->uidp;
+
+  if (uidp && uidp->unp) {
+    memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
+    ioctlp->outDatap += strlen(uidp->unp->name);
+       }
+
+  return 0;
+}
+
+/* 
+ * functions to dump contents of various structures. 
+ * In debug build (linked with crt debug library) will dump allocated but not freed memory
+ */
+extern int cm_DumpSCache(FILE *outputFile, char *cookie);
+extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie);
+extern int smb_DumpVCP(FILE *outputFile, char *cookie);
+
+long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    long inValue = 0;
+    HANDLE hLogFile;
+    char logfileName[MAX_PATH+1];
+    char *cookie;
+  
+#ifdef _DEBUG  
+    static _CrtMemState memstate;
+#endif
+  
+    cm_SkipIoctlPath(ioctlp);
+    memcpy(&inValue, ioctlp->inDatap, sizeof(long));
+  
+    GetWindowsDirectory(logfileName, sizeof(logfileName));
+    strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
+
+    hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  
+    if (!hLogFile)
+    {
+      /* error */
+      inValue = -1;
+      memcpy(ioctlp->outDatap, &inValue, sizeof(long));
+      ioctlp->outDatap += sizeof(long);
+      
+      return 0;               
+    }
+  
+    SetFilePointer(hLogFile, 0, NULL, FILE_END);
+  
+    cookie = inValue ? "b" : "e";
+  
+#ifdef _DEBUG  
+  
+    if (inValue)
+    {
+      _CrtMemCheckpoint(&memstate);           
+    }
+    else
+    {
+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+        _CrtSetReportFile(_CRT_WARN, hLogFile);
+        _CrtMemDumpAllObjectsSince(&memstate);
+    }
+#endif
+  
+    /* dump all interesting data */
+    cm_DumpSCache(hLogFile, cookie);
+    cm_DumpBufHashTable(hLogFile, cookie);
+    smb_DumpVCP(hLogFile, cookie);
+
+    CloseHandle(hLogFile);                          
+  
+    memcpy(ioctlp->outDatap, &inValue, sizeof(long));
+    ioctlp->outDatap += sizeof(long);
+  
+    return 0;
+}