windows-afsdb-and-freelance-afs-root-support-20011005
authorJeff Riegel <riegel@almaden.ibm.com>
Fri, 5 Oct 2001 22:40:44 +0000 (22:40 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 5 Oct 2001 22:40:44 +0000 (22:40 +0000)
afsdb record support for windows
freelance /afs (make up an afs root instead of using root.afs from some cell)
support for windows

38 files changed:
src/Makefile.djgpp
src/NTMake9x
src/NTMakefile
src/WINNT/afsd/Makefile.djgpp
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd95.c
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/afsd_init95.c
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_cell.h
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_config.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dns.c [new file with mode: 0644]
src/WINNT/afsd/cm_dns.h [new file with mode: 0644]
src/WINNT/afsd/cm_dns_private.h [new file with mode: 0644]
src/WINNT/afsd/cm_freelance.c [new file with mode: 0644]
src/WINNT/afsd/cm_freelance.h [new file with mode: 0644]
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/libafsconf.def
src/WINNT/client_osi/osisleep.h
src/auth/NTMakefile
src/auth/cellconfig.c
src/config/Makefile.i386_djgpp
src/config/NTMakefile.i386_nt40
src/config/NTMakefile.i386_win95
src/config/afsconfig-windows.h
src/kauth/NTMakefile
src/kauth/kpasswd.c
src/kauth/user_nt.c
src/libafsauthent/NTMakefile
src/ptserver/NTMakefile
src/ptserver/pts.c

index e0316f8..23f2dce 100644 (file)
@@ -4,7 +4,10 @@
 
 OBJ = $(SYS_NAME)/obj
 DEST = $(SYS_NAME)/dest
+DESTDIR = DEST/
+SRCDIR = ${DESTDIR}
 #LINUX_SYS = i386_linux22
+TOP_SRCDIR = `pwd`/src
 
 all: afsd
 
index 2e76674..8fb9842 100644 (file)
@@ -179,7 +179,13 @@ sys: cm_headers
        $(NTMAKE)
        $(CD) ..\..
 
-auth: sys
+afsdobjs: sys
+     echo ***** $@
+     $(CD) $(OBJ)\WINNT\afsd
+     $(NTMAKE_OBJS)
+     $(CD) ..\..\..
+
+auth: afsdobjs
      echo ***** $@
        $(CD) $(OBJ)\$@
        $(NTMAKE)
index 268119a..07cc29a 100644 (file)
@@ -21,6 +21,7 @@ CD = cd
 NTMAKE = nmake /nologo /f ntmakefile install
 NTMAKELANG = nmake /nologo /f ntmakefile en_US
 NTMAKE_HEADERS = nmake /nologo /f ntmakefile install_headers
+NTMAKE_OBJS = nmake /nologo /f ntmakefile install_objs
 MKDIR = mkdir
 OBJ = src
 
@@ -178,7 +179,13 @@ sys: cm_headers
        $(NTMAKE)
        $(CD) ..\..
 
-auth: sys
+afsdobjs: sys
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\afsd
+       $(NTMAKE_OBJS)
+       $(CD) ..\..\..
+
+auth: afsdobjs
      echo ***** $@
        $(CD) $(OBJ)\$@
        $(NTMAKE)
index 6788573..8848874 100644 (file)
@@ -9,7 +9,8 @@ SOURCES    = afsd95.c afsd_init95.c cm_access.c cm_aclent.c cm_buf.c \
                cm_dcache.c cm_dir.c cm_dnlc.c cm_ioctl.c cm_scache.c \
                cm_server.c cm_user.c cm_utils.c cm_vnodeops.c cm_volume.c \
                dosutils95.c largeint95.c netbios95.c smb.c smb_ioctl.c \
-               cm_diskcache95.c queue95.c afsmsg95.c smb3.c
+               cm_diskcache95.c queue95.c afsmsg95.c smb3.c cm_dns.c \
+               cm_freelance.c
 
 include ../../config/Makefile.djgpp.common
 
@@ -24,7 +25,7 @@ all : $(TARGETS)
 install : $(DESTBIN)/afsd.exe #$(DESTBIN)/klog.exe
 #CFLAGS += -I../vxd_lib
 #CFLAGS += -DAFS_VXD
-CFLAGS += -DDOS_PKT_WHOLE
+CFLAGS += -DDOS_PKT_WHOLE -DAFS_AFSDB_ENV -DAFS_FREELANCE_CLIENT
 
 INCFILES = \
         $(DESTINC)/netbios95.h \
index e8e33da..4e5af5a 100644 (file)
@@ -36,12 +36,15 @@ INCFILES =\
        $(INCFILEDIR)\smb_iocons.h \
        $(INCFILEDIR)\smb_ioctl.h \
        $(INCFILEDIR)\afsmsg95.h \
-       $(INCFILEDIR)\afsrpc.h
+       $(INCFILEDIR)\afsrpc.h \
+       $(INCFILEDIR)\cm_dns.h \
+       $(INCFILEDIR)\cm_dns_private.h
 
 IDLFILES =\
        afsrpc.h afsrpc_c.obj
 
-CONFOBJS=cm_config.obj
+CONFOBJS=cm_config.obj \
+         cm_dns.obj
 
 AFSDOBJS=\
        afsd_init.obj \
@@ -66,7 +69,8 @@ AFSDOBJS=\
        cm_aclent.obj \
        cm_dnlc.obj \
        cm_rpc.obj \
-       afsrpc_s.obj
+       afsrpc_s.obj \
+     cm_freelance.obj
 
 cm_conn.obj: cm_conn.c
        $(C2OBJ) -DAFS_PTHREAD_ENV $**
@@ -153,6 +157,10 @@ $(LOG95_DLLFILE): $(LOG95_DLLOBJS)
 ############################################################################
 # Install target; primary makefile target
 
+install_objs: cm_dns.obj cm_config.obj
+     $(COPY) cm_dns.obj $(DESTDIR)\lib
+     $(COPY) cm_config.obj $(DESTDIR)\lib
+
 install_headers: $(IDLFILES) $(INCFILES)
 
 install: install_headers $(CONF_DLLFILE) \
index 0c6f59f..6456c71 100644 (file)
@@ -35,7 +35,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 
 #include "krb.h"
 #include "krb_prot.h"
-#include <crypt.h>
+/*#include <crypt.h>*/
 #include <afs/prs_fs.h>
 
 #include <osi.h>
@@ -60,6 +60,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include "cm_ioctl.h"
 #include "cm_dnlc.h"
 #include "cm_buf.h"
+#include "cm_freelance.h"
 #ifdef DJGPP
 #include "afs/afsmsg95.h"
 #endif
@@ -96,4 +97,30 @@ extern BOOL isGateway;
 
 extern BOOL reportSessionStartups;
 
+#ifdef AFS_FREELANCE_CLIENT
+
+// yj: Variables used by Freelance Client
+extern char *cm_FakeRootDir;                                           // the fake root.afs directory
+
+extern int cm_noLocalMountPoints;                                      // no. of fake mountpoints
+
+extern cm_localMountPoint_t* cm_localMountPoints;      // array of fake mountpoints
+
+extern int cm_fakeDirSize;                                                     // size (in bytes) of fake root.afs directory
+
+extern int cm_fakeDirCallback;                                         // state of the fake root.afs directory. indicates
+                                                                                                       // if it needs to be refreshed
+
+extern int cm_fakeGettingCallback;                                     // 1 if currently updating the fake root.afs directory,
+                                                                                                       // 0 otherwise
+
+extern int cm_fakeDirVersion;                                          // the version number of the root.afs directory. used 
+                                                                                                       // invalidate all the buffers containing root.afs data
+                                                                                                       // after reinitialization
+// ------------------------------------------
+#endif /* AFS_FREELANCE_CLIENT */
+
+extern int cm_dnsEnabled;
+extern int cm_freelanceEnabled;
+
 #endif /* AFSD_H_ENV */
index 3aa6bc7..75cd53a 100644 (file)
@@ -95,6 +95,8 @@ int main(int argc, char *argv[])
     cmd_AddParm(ts, "-tracebuf", CMD_SINGLE, CMD_OPTIONAL, "trace buffer size");
     cmd_AddParm(ts, "-startup", CMD_FLAG, CMD_OPTIONAL, "start AFS client");
     cmd_AddParm(ts, "-diskcache", CMD_SINGLE, CMD_OPTIONAL, "diskcache size");
+    cmd_AddParm(ts, "-afsdb", CMD_FLAG, CMD_OPTIONAL, "use DNS for cell server resolution");
+    cmd_AddParm(ts, "-freelance", CMD_FLAG, CMD_OPTIONAL, "virtual AFS root");
 
     return (cmd_Dispatch(argc, argv));
 }
index 48cecb4..a09e4c1 100644 (file)
@@ -48,6 +48,9 @@ char cm_mountRoot[1024];
 DWORD cm_mountRootLen;
 int cm_logChunkSize;
 int cm_chunkSize;
+#ifdef AFS_FREELANCE_CLIENT
+char *cm_FakeRootDir;
+#endif /* freelance */
 
 int smb_UseV3;
 
@@ -82,6 +85,16 @@ cm_initparams_v1 cm_initParams;
 
 HANDLE afsi_file;
 
+#ifdef AFS_AFSDB_ENV
+int cm_dnsEnabled = 1;
+#endif
+
+/*#ifdef AFS_FREELANCE_CLIENT
+extern int cm_freelanceEnabled;
+#endif*/
+
+void cm_InitFakeRootDir();
+
 void
 afsi_start()
 {
@@ -167,6 +180,7 @@ int afsd_InitCM(char **reasonP)
        HKEY parmKey;
        DWORD dummyLen;
        long code;
+       /*int freelanceEnabled;*/
        WSADATA WSAjunk;
 
        WSAStartup(0x0101, &WSAjunk);
@@ -392,6 +406,32 @@ int afsd_InitCM(char **reasonP)
                afsi_log("Default SecurityLevel is clear");
        }
 
+#ifdef AFS_AFSDB_ENV
+       dummyLen = sizeof(cm_dnsEnabled);
+       code = RegQueryValueEx(parmKey, "UseDNS", NULL, NULL,
+                               (BYTE *) &cm_dnsEnabled, &dummyLen);
+       if (code == ERROR_SUCCESS) {
+               afsi_log("DNS %s be used to find AFS cell servers",
+                        cm_dnsEnabled ? "will" : "will not");
+       }
+       else {
+         cm_dnsEnabled = 1;   /* default on */
+       }
+#endif /* AFS_AFSDB_ENV */
+
+#ifdef AFS_FREELANCE_CLIENT
+       dummyLen = sizeof(cm_freelanceEnabled);
+       code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
+                               (BYTE *) &cm_freelanceEnabled, &dummyLen);
+       if (code == ERROR_SUCCESS) {
+               afsi_log("Freelance client feature %s activated",
+                        cm_freelanceEnabled ? "is" : "is not");
+       }
+       else {
+         cm_freelanceEnabled = 0;  /* default off */
+       }
+#endif /* AFS_FREELANCE_CLIENT */
+
        RegCloseKey (parmKey);
 
        /* setup early variables */
@@ -497,20 +537,35 @@ int afsd_InitCM(char **reasonP)
                return -1;
        }
 
+#ifdef AFS_AFSDB_ENV
+       if (cm_InitDNS(cm_dnsEnabled) == -1)
+         cm_dnsEnabled = 0;  /* init failed, so deactivate */
+       afsi_log("cm_InitDNS %d", cm_dnsEnabled);
+#endif
+
        code = cm_GetRootCellName(rootCellName);
        afsi_log("cm_GetRootCellName code %d rcn %s", code,
                 (code ? "<none>" : rootCellName));
-       if (code != 0) {
-               *reasonP = "can't find root cell name in afsd.ini";
-               return -1;
+       if (code != 0 && !cm_freelanceEnabled) {
+           *reasonP = "can't find root cell name in afsd.ini";
+           return -1;
+        }
+        else if (cm_freelanceEnabled)
+          cm_rootCellp = NULL;
+
+        if (code == 0 && !cm_freelanceEnabled) {
+         cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
+          afsi_log("cm_GetCell addr %x", cm_rootCellp);
+         if (cm_rootCellp == NULL) {
+           *reasonP = "can't find root cell in afsdcell.ini";
+           return -1;
+         }
        }
 
-       cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
-       afsi_log("cm_GetCell addr %x", cm_rootCellp);
-       if (cm_rootCellp == NULL) {
-               *reasonP = "can't find root cell in afsdcell.ini";
-               return -1;
-       }
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled)
+         cm_InitFreelance();
+#endif
 
        return 0;
 }
@@ -524,19 +579,26 @@ int afsd_InitDaemons(char **reasonP)
 
        /* this should really be in an init daemon from here on down */
 
-       code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,                &req, CM_FLAG_CREATE, &cm_rootVolumep);
-       afsi_log("cm_GetVolumeByName code %x root vol %x", code,
-                (code ? 0xffffffff : cm_rootVolumep));
-       if (code != 0) {
-               *reasonP = "can't find root volume in root cell";
-               return -1;
+        if (!cm_freelanceEnabled) {
+          code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,
+                                    &req, CM_FLAG_CREATE, &cm_rootVolumep);
+          afsi_log("cm_GetVolumeByName code %x root vol %x", code,
+                   (code ? 0xffffffff : cm_rootVolumep));
+          if (code != 0) {
+            *reasonP = "can't find root volume in root cell";
+            return -1;
+          }
         }
 
-        /* compute the root fid */
-       cm_rootFid.cell = cm_rootCellp->cellID;
-        cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
-        cm_rootFid.vnode = 1;
-        cm_rootFid.unique = 1;
+       /* compute the root fid */
+       if (!cm_freelanceEnabled) {
+         cm_rootFid.cell = cm_rootCellp->cellID;
+         cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
+         cm_rootFid.vnode = 1;
+         cm_rootFid.unique = 1;
+       }
+       else
+         cm_FakeRootFid(&cm_rootFid);
         
         code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
        afsi_log("cm_GetSCache code %x scache %x", code,
@@ -575,3 +637,4 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
 
        return 0;
 }
+
index 602255f..cdd9ffe 100644 (file)
@@ -47,6 +47,14 @@ int cm_chunkSize;
 int afs_diskCacheChunks;
 char cm_cachePath[128];
 int cm_diskCacheEnabled = 0;
+#ifdef AFS_AFSDB_ENV
+extern int cm_dnsEnabled;
+#endif
+
+#ifdef AFS_FREELANCE_CLIENT
+extern int cm_freelanceEnabled;
+char *cm_FakeRootDir;
+#endif /* freelance */
 
 int smb_UseV3;
 
@@ -84,6 +92,7 @@ BOOL reportSessionStartups = FALSE;
 int afsd_debug;
 cm_initparams_v1 cm_initParams;
 
+
 /*
  * AFSD Initialization Log
  *
@@ -555,6 +564,16 @@ int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock)
           afsi_log("Default disk cache size %d", diskCacheSize);
         }
 
+        if (as->parms[22].items) {
+           /* -noafsdb */
+           cm_dnsEnabled = 0;
+        }
+
+        if (as->parms[23].items) {
+           /* -freelance */
+           cm_freelanceEnabled = 1;
+        }
+
         if (ParseCacheInfoFile()) {
           exit(1);
         }
@@ -638,6 +657,13 @@ int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock)
         rx_StartServer(0);
        afsi_log("rx_StartServer");
 
+#ifdef AFS_AFSDB_ENV
+       /* initialize dns lookup */
+       if (cm_InitDNS(cm_dnsEnabled) == -1)
+         cm_dnsEnabled = 0;  /* init failed, so deactivate */
+       afsi_log("cm_InitDNS %d", cm_dnsEnabled);
+#endif
+
        /* init user daemon, and other packages */
        cm_InitUser();
 
@@ -670,18 +696,27 @@ int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock)
        code = cm_GetRootCellName(rootCellName);
        afsi_log("cm_GetRootCellName code %d rcn %s", code,
                 (code ? "<none>" : rootCellName));
-       if (code != 0) {
+       if (code != 0 && !cm_freelanceEnabled) {
                *reasonP = "can't find root cell name in ThisCell";
                return -1;
        }
-
-       cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
-       afsi_log("cm_GetCell addr %x", cm_rootCellp);
-       if (cm_rootCellp == NULL) {
-               *reasonP = "can't find root cell in CellServDB";
-               return -1;
+       else if (cm_freelanceEnabled)
+         cm_rootCellp = NULL;
+       
+       if (code == 0 && !cm_freelanceEnabled) {
+         cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
+         afsi_log("cm_GetCell addr %x", cm_rootCellp);
+         if (cm_rootCellp == NULL) {
+           *reasonP = "can't find root cell in CellServDB";
+           return -1;
+         }
        }
 
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled)
+         cm_InitFreelance();
+#endif
+
        return 0;
 }
 
@@ -694,19 +729,25 @@ int afsd_InitDaemons(char **reasonP)
 
        /* this should really be in an init daemon from here on down */
 
-       code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,                &req, CM_FLAG_CREATE, &cm_rootVolumep);
-       afsi_log("cm_GetVolumeByName code %x root vol %x", code,
-                (code ? 0xffffffff : cm_rootVolumep));
-       if (code != 0) {
-               *reasonP = "can't find root volume in root cell";
-               return -1;
-        }
+       if (!cm_freelanceEnabled) { 
+         code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,              &req, CM_FLAG_CREATE, &cm_rootVolumep);
+         afsi_log("cm_GetVolumeByName code %x root vol %x", code,
+                  (code ? 0xffffffff : cm_rootVolumep));
+         if (code != 0) {
+           *reasonP = "can't find root volume in root cell";
+           return -1;
+         }
+       }
 
         /* compute the root fid */
-       cm_rootFid.cell = cm_rootCellp->cellID;
-        cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
-        cm_rootFid.vnode = 1;
-        cm_rootFid.unique = 1;
+       if (!cm_freelanceEnabled) {
+         cm_rootFid.cell = cm_rootCellp->cellID;
+         cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
+         cm_rootFid.vnode = 1;
+         cm_rootFid.unique = 1;
+       }
+       else
+         cm_FakeRootFid(&cm_rootFid);
         
         code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
        afsi_log("cm_GetSCache code %x scache %x", code,
@@ -744,3 +785,4 @@ int afsd_InitSMB(char **reasonP)
 
        return 0;
 }
+
index f00938a..959b35a 100644 (file)
 /* read/write lock for all global storage in this module */
 osi_rwlock_t cm_callbackLock;
 
+/*
+#ifdef AFS_FREELANCE_CLIENT
+extern int cm_fakeDirCallback;
+extern int cm_fakeGettingCallback;
+#endif
+*/
+#ifdef AFS_FREELANCE_CLIENT
+extern osi_mutex_t cm_Freelance_Lock;
+#endif
+
 /* count of # of callback breaking messages received by this CM so far.  We use
  * this count in determining whether there have been any callback breaks that
  * apply to a call that returned a new callback.  If the counter doesn't
@@ -568,9 +578,50 @@ void cm_InitCallback(void)
  */
 int cm_HaveCallback(cm_scache_t *scp)
 {
-       if (scp->cbServerp != NULL)
-               return 1;
-       else return 0;
+#ifdef AFS_FREELANCE_CLIENT
+    // yj: we handle callbacks specially for callbacks on the root directory
+    // Since it's local, we almost always say that we have callback on it
+    // The only time we send back a 0 is if we're need to initialize or
+    // reinitialize the fake directory
+
+    // There are 2 state variables cm_fakeGettingCallback and cm_fakeDirCallback
+    // cm_fakeGettingCallback is 1 if we're in the process of initialization and
+    // hence should return false. it's 0 otherwise
+    // cm_fakeDirCallback is 0 if we haven't loaded the fake directory, it's 1
+    // if the fake directory is loaded and this is the first time cm_HaveCallback
+    // is called since then. We return false in this case to allow cm_GetCallback
+    // to be called because cm_GetCallback has some initialization work to do.
+    // If cm_fakeDirCallback is 2, then it means that the fake directory is in
+    // good shape and we simply return true, provided no change is detected.
+  int fdc, fgc;
+
+    if (cm_freelanceEnabled && scp->fid.cell==0x1 && scp->fid.volume==0x20000001) {    // if it's something on /afs
+       if (!(scp->fid.vnode==0x1 && scp->fid.unique==0x1))     // if it's not root.afs
+           return 1;
+       else {
+           lock_ObtainMutex(&cm_Freelance_Lock);
+           fdc = cm_fakeDirCallback;
+           fgc = cm_fakeGettingCallback;
+           lock_ReleaseMutex(&cm_Freelance_Lock);
+           
+           if (fdc==1) {       // first call since init
+               return 0;
+           } else if (fdc==2 && !fgc) {        // we're in good shape
+               if (cm_getLocalMountPointChange()) {    // check for changes
+                   cm_clearLocalMountPointChange(); // clear the changefile
+                   cm_reInitLocalMountPoints();        // start reinit
+                   return 0;
+               }
+               return 1;                       // no change
+           }
+           return 0;
+       }
+    }
+#endif
+
+    if (scp->cbServerp != NULL)
+       return 1;
+    else return 0;
 }
 
 /* need to detect a broken callback that races with our obtaining a callback.
@@ -694,6 +745,43 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
         int mustCall;
         long sflags;
 
+#ifdef AFS_FREELANCE_CLIENT
+       // yj
+       // The case where a callback is needed on /afs is handled
+       // specially. We need to fetch the status by calling
+       // cm_MergeStatus and mark that cm_fakeDirCallback is 2
+       if (cm_freelanceEnabled &&
+          scp->fid.cell==0x1 &&
+               scp->fid.volume==0x20000001 &&
+               scp->fid.unique==0x1 &&
+               scp->fid.vnode==0x1) {
+               // Start by indicating that we're in the process
+               // of fetching the callback
+
+               lock_ObtainMutex(&cm_Freelance_Lock);
+               cm_fakeGettingCallback = 1;
+               lock_ReleaseMutex(&cm_Freelance_Lock);
+
+               // Fetch the status info 
+               cm_MergeStatus(scp, &afsStatus, &volSync, userp, 0);
+
+               // Indicate that the callback is not done
+               lock_ObtainMutex(&cm_Freelance_Lock);
+               cm_fakeDirCallback = 2;
+               // Indicate that we're no longer fetching the callback
+               cm_fakeGettingCallback = 0;
+               lock_ReleaseMutex(&cm_Freelance_Lock);
+
+               return 0;
+       }
+
+       /*if (scp->fid.cell==0x1 && scp->fid.volume==0x20000001) {
+               afsi_log("cm_getcallback should NEVER EVER get here... ");
+       }*/
+       // yj: end of getcallback modifications  ---------------
+               
+#endif /* AFS_FREELANCE_CLIENT */
+       
        mustCall = (flags & 1);
        cm_AFSFidFromFid(&tfid, &scp->fid);
        while (1) {
index b8317eb..5ef16bc 100644 (file)
@@ -60,20 +60,38 @@ cm_cell_t *cm_GetCell(char *namep, long flags)
        cm_cell_t *cp;
         long code;
         static cellCounter = 1;                /* locked by cm_cellLock */
+       int ttl;
 
        lock_ObtainWrite(&cm_cellLock);
        for(cp = cm_allCellsp; cp; cp=cp->nextp) {
                if (strcmp(namep, cp->namep) == 0) break;
         }
-       if (!cp && (flags & CM_FLAG_CREATE)) {
-               cp = malloc(sizeof(*cp));
+
+       if ((!cp && (flags & CM_FLAG_CREATE))
+#ifdef AFS_AFSDB_ENV
+           /* if it's from DNS, see if it has expired */
+           || (cp && (cp->flags & CM_CELLFLAG_DNS) && (time(0) > cp->timeout))
+#endif
+         ) {
+               if (!cp) cp = malloc(sizeof(*cp));
                 memset(cp, 0, sizeof(*cp));
                 code = cm_SearchCellFile(namep, NULL, cm_AddCellProc, cp);
-                if (code) {
-                       free(cp);
-                        cp = NULL;
-                        goto done;
-                }
+#ifdef AFS_AFSDB_ENV
+                if (code && cm_dnsEnabled) {
+                  code = cm_SearchCellByDNS(namep, NULL, &ttl, cm_AddCellProc, cp);
+#endif
+                 if (code) {
+                   free(cp);
+                   cp = NULL;
+                   goto done;
+                 }
+#ifdef AFS_AFSDB_ENV
+                 else {   /* got cell from DNS */
+                   cp->flags |= CM_CELLFLAG_DNS;
+                   cp->timeout = time(0) + ttl;
+                 }
+               }
+#endif
 
                /* randomise among those vlservers having the same rank*/ 
                cm_RandomizeServer(&cp->vlServersp);
@@ -100,11 +118,30 @@ done:
 cm_cell_t *cm_FindCellByID(long cellID)
 {
        cm_cell_t *cp;
+       int ttl;
+     int code;
 
        lock_ObtainWrite(&cm_cellLock);
        for(cp = cm_allCellsp; cp; cp=cp->nextp) {
                if (cellID == cp->cellID) break;
         }
+
+#ifdef AFS_AFSDB_ENV
+       /* if it's from DNS, see if it has expired */
+       if (cp && cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && (time(0) > cp->timeout)) {
+         code = cm_SearchCellByDNS(cp->namep, NULL, &ttl, cm_AddCellProc, cp);
+         if (code == 0) {   /* got cell from DNS */
+           cp->flags |= CM_CELLFLAG_DNS;
+#ifdef DEBUG
+           fprintf(stderr, "cell %s: ttl=%d\n", cp->namep, ttl);
+#endif
+           cp->timeout = time(0) + ttl;
+         }
+         /* if we fail to find it this time, we'll just do nothing and leave the
+            current entry alone */
+       }
+#endif /* AFS_AFSDB_ENV */
+
        lock_ReleaseWrite(&cm_cellLock);        
        
         return cp;
index ca0ae38..a642d04 100644 (file)
@@ -20,9 +20,11 @@ typedef struct cm_cell {
         struct cm_serverRef *vlServersp;       /* locked by cm_serverLock */
         osi_mutex_t mx;                        /* mutex locking fields (flags) */
         long flags;                    /* locked by mx */
+        long timeout;                   /* if dns, time at which the server addrs expire */
 } cm_cell_t;
 
 #define CM_CELLFLAG_SUID       1       /* setuid flag; not yet used */
+#define CM_CELLFLAG_DNS         2       /* cell servers are from DNS */
 
 extern void cm_InitCell(void);
 
index a3ef82f..10a0d44 100644 (file)
 #include <string.h>
 
 #include "cm_config.h"
+#ifdef AFS_AFSDB_ENV
+#include "cm_dns.h"
+#include <afs/afsint.h>
+#endif
 
 char AFSConfigKeyName[] =
        "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
@@ -276,6 +280,35 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
         }              /* while loop processing all lines */
 }
 
+long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
+               cm_configProc_t *procp, void *rockp)
+{
+#ifdef AFS_AFSDB_ENV
+     int rc;
+     int cellHosts[AFSMAXCELLHOSTS];
+     int numServers;
+     int i;
+     struct sockaddr_in vlSockAddr;
+
+     rc = getAFSServer(cellNamep, cellHosts, &numServers, ttl);
+     if (rc == 0 && numServers > 0) {     /* found the cell */
+       for (i = 0; i < numServers; i++) {
+           memcpy(&vlSockAddr.sin_addr.s_addr, &cellHosts[i],
+               sizeof(long));
+           vlSockAddr.sin_family = AF_INET;
+           /* sin_port supplied by connection code */
+           if (procp)
+          (*procp)(rockp, &vlSockAddr, NULL);
+           if(newCellNamep)
+          strcpy(newCellNamep,cellNamep);
+       }
+       return 0;   /* found cell */
+     }
+     else
+#endif /* AFS_AFSDB_ENV */
+       return -1;  /* not found */
+}
+
 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
 /* look up the root cell's name in the Registry */
 long cm_GetRootCellName(char *cellNamep)
@@ -553,3 +586,32 @@ extern long cm_CloseCellFile(cm_configFile_t *filep)
         
         return code;
 }
+
+void cm_GetConfigDir(char *dir)
+{
+       char wdir[256];
+     char *afsconf_path;
+     int code;
+     int tlen;
+
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
+       code = GetWindowsDirectory(wdir, sizeof(wdir));
+      if (code == 0 || code > sizeof(wdir)) wdir[0] = 0;
+        
+       /* add trailing backslash, if required */
+        tlen = strlen(wdir);
+        if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
+#else
+#ifdef DJGPP
+        strcpy(wdir,cm_confDir);
+#else
+        afsconf_path = getenv("AFSCONF");
+        if (!afsconf_path)
+          strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
+        else
+          strcpy(wdir, afsconf_path);
+#endif /* !DJGPP */
+        strcat(wdir,"\\");
+#endif /* DJGPP || WIN95 */
+        strcpy(dir, wdir);
+}
index 19ab236..11996e5 100644 (file)
@@ -36,6 +36,9 @@ extern long cm_GetRootCellName(char *namep);
 extern long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
        cm_configProc_t *procp, void *rockp);
 
+extern long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
+               cm_configProc_t *procp, void *rockp);
+
 extern long cm_WriteConfigString(char *labelp, char *valuep);
 
 extern long cm_WriteConfigInt(char *labelp, long value);
index 69a08cd..6a7a3ac 100644 (file)
@@ -23,6 +23,9 @@
 #include "afsd.h"
 
 osi_mutex_t cm_bufGetMutex;
+#ifdef AFS_FREELANCE_CLIENT
+extern osi_mutex_t cm_Freelance_Lock;
+#endif
 
 /* functions called back from the buffer package when reading or writing data,
  * or when holding or releasing a vnode pointer.
@@ -1075,11 +1078,23 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
         struct rx_call *callp;
         cm_bulkIO_t biod;              /* bulk IO descriptor */
         cm_conn_t *connp;
+       int getroot;
+       long t1, t2;
 
         /* now, the buffer may or may not be filled with good data (buf_GetNew
          * drops lots of locks, and may indeed return a properly initialized
          * buffer, although more likely it will just return a new, empty, buffer.
          */
+
+#ifdef AFS_FREELANCE_CLIENT
+
+       // yj: if they're trying to get the /afs directory, we need to
+       // handle it differently, since it's local rather than on any
+       // server
+
+       getroot = (scp==cm_rootSCachep) ;
+#endif
+
        cm_AFSFidFromFid(&tfid, &scp->fid);
 
        code = cm_SetupFetchBIOD(scp, &bufp->offset, &biod, up, reqp);
@@ -1120,6 +1135,73 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                 scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
 #endif /* DISKCACHE95 */
 
+#ifdef AFS_FREELANCE_CLIENT
+
+       // yj code
+       // if getroot then we don't need to make any calls
+       // just return fake data
+       
+        if (cm_freelanceEnabled && getroot) {
+               // setup the fake status                        
+               afsStatus.InterfaceVersion = 0x1;
+               afsStatus.FileType = 0x2;
+               afsStatus.LinkCount = scp->linkCount;
+               afsStatus.Length = cm_fakeDirSize;
+               afsStatus.DataVersion = cm_fakeDirVersion;
+               afsStatus.Author = 0x1;
+               afsStatus.Owner = 0x0;
+               afsStatus.CallerAccess = 0x9;
+               afsStatus.AnonymousAccess = 0x9;
+               afsStatus.UnixModeBits = 0x1ff;
+               afsStatus.ParentVnode = 0x1;
+               afsStatus.ParentUnique = 0x1;
+               afsStatus.SegSize = 0;
+               afsStatus.ClientModTime = 0x3b49f6e2;
+               afsStatus.ServerModTime = 0x3b49f6e2;
+               afsStatus.Group = 0;
+               afsStatus.SyncCounter = 0;
+               afsStatus.dataVersionHigh = 0;
+       
+               // once we're done setting up the status info,
+               // we just fill the buffer pages with fakedata
+               // from cm_FakeRootDir. Extra pages are set to
+               // 0. 
+               
+               lock_ObtainMutex(&cm_Freelance_Lock);
+#ifdef DEBUG
+               afsi_log("bufp->offset is %d", bufp->offset);
+#endif
+               t1 = bufp->offset.LowPart;
+               qdp = biod.bufListEndp;
+               while (qdp) {
+                       tbufp = osi_GetQData(qdp);
+                       bufferp=tbufp->datap;
+                       memset(bufferp, 0, buf_bufferSize);
+                       t2 = cm_fakeDirSize - t1;
+                       if (t2>buf_bufferSize) t2=buf_bufferSize;
+#ifdef DEBUG
+                       afsi_log("t1:%d, t2:%d", t1, t2);
+#endif
+                       if (t2 > 0) {
+                               memcpy(bufferp, cm_FakeRootDir+t1, t2);
+                       } else {
+                               t2 = 0;
+                       }
+                       t1+=t2;
+                       qdp = (osi_queueData_t *) osi_QPrev(&qdp->q);
+                       
+               }
+               lock_ReleaseMutex(&cm_Freelance_Lock);
+       
+               // once we're done, we skip over the part of the
+               // code that does the ACTUAL fetching of data for
+               // real files
+
+               goto fetchingcompleted;
+       }
+
+#endif /* AFS_FREELANCE_CLIENT */
+
        /* now make the call */
         do {
                code = cm_Conn(&scp->fid, up, reqp, &connp);
@@ -1230,6 +1312,8 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                 osi_Log0(afsd_logp, "CALL FetchData DONE");
                 
        } while (cm_Analyze(connp, up, reqp, &scp->fid, &volSync, NULL, code));
+
+  fetchingcompleted:
         code = cm_MapRPCError(code, reqp);
 
         lock_ObtainMutex(&scp->mx);
diff --git a/src/WINNT/afsd/cm_dns.c b/src/WINNT/afsd/cm_dns.c
new file mode 100644 (file)
index 0000000..b0e1da0
--- /dev/null
@@ -0,0 +1,687 @@
+/* Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifdef AFS_AFSDB_ENV
+
+#include <afs/param.h>
+#include <afs/stds.h>
+#ifndef DJGPP
+#include <windows.h>
+#include <winsock2.h>
+#endif
+#include "cm_dns_private.h"
+#include "cm_dns.h"
+#include <lwp.h>
+#include <afs/afsint.h>
+
+extern int errno;
+static char dns_addr[30];
+#ifdef DJGPP
+extern char cm_confDir[];
+#endif
+int cm_dnsEnabled = -1;
+
+void DNSlowerCase(char *str)
+{
+  int i;
+
+  for (i=0; i<strlen(str); i++)
+    /*str[i] = tolower(str[i]);*/
+    if (str[i] >= 'A' && str[i] <= 'Z')
+      str[i] += 'a' - 'A';
+}
+
+int cm_InitDNS(int enabled)
+{
+  char configpath[100];
+  int len;
+  int code;
+  char *path;
+  char *addr;
+  
+  if (!enabled) { fprintf(stderr, "DNS support disabled\n"); cm_dnsEnabled = 0; return 0; }
+
+  /* First try AFS_NS environment var. */
+  addr = getenv("AFS_NS");
+  if (addr && inet_addr(addr) != -1) {
+    strcpy(dns_addr, addr);
+  } else {
+    /* Now check for the AFSDNS.INI file */
+#ifdef DJGPP
+    strcpy(configpath, cm_confDir);
+#elif defined(AFS_WIN95_ENV)
+    path = getenv("AFSCONF");
+    if (path) strcpy(configpath, path);
+    else strcpy(configpath, "c:\\afscli");
+#else  /* nt */
+    code = GetWindowsDirectory(configpath, sizeof(configpath));
+    if (code == 0 || code > sizeof(configpath)) return -1;
+#endif
+    strcat(configpath, "\\afsdns.ini");
+
+    /* Currently we only get (and query) the first nameserver.  Getting
+       list of mult. nameservers should be easy to do. */
+    len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
+                           dns_addr, sizeof(dns_addr),
+                           configpath);
+  
+    if (len == 0 || inet_addr(dns_addr) == -1) {
+      fprintf(stderr, "No valid name server addresses found, DNS lookup is "
+                      "disabled\n");
+      cm_dnsEnabled = 0;  /* failed */
+      return -1;     /* No name servers defined */
+    }
+    else fprintf(stderr, "Found DNS server %s\n", dns_addr);
+  }
+
+  cm_dnsEnabled = 1;
+  return 0;
+}
+
+SOCKADDR_IN setSockAddr(char *server, int port)
+{
+  SOCKADDR_IN sockAddr;                     
+  int         addrLen = sizeof(SOCKADDR_IN);
+
+#ifndef WIN32_LEAN_AND_MEAN
+  bzero(&sockAddr,addrLen);
+#endif /*WIN32_LEAN_AND_MEAN*/
+  sockAddr.sin_family   = AF_INET;
+  sockAddr.sin_port     = htons( port );
+  sockAddr.sin_addr.s_addr = inet_addr( server );
+  /*inet_aton(server, &sockAddr.sin_addr.s_addr);*/
+
+  return (sockAddr);
+}
+
+int getRRCount(PDNS_HDR ptr)
+{
+  return(ntohs(ptr->rr_count));
+}
+
+
+int send_DNS_Addr_Query(char* query, 
+                        SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
+{
+  PDNS_HDR    pDNShdr;
+  PDNS_QTAIL  pDNS_qtail;
+
+  int     queryLen = 0;
+  int     res;
+
+#ifndef WIN32_LEAN_AND_MEAN
+  bzero(buffer,BUFSIZE);
+#endif /*WIN32_LEAN_AND_MEAN*/
+
+  /*********************************
+   * Build DNS Query Message       *
+   *                               *
+   * hard-coded Adrress (A) query  *
+   *********************************/
+  
+  pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
+  pDNShdr->id         = htons( 0xDADE );
+  pDNShdr->flags      = htons( DNS_FLAG_RD ); /* do recurse */
+  pDNShdr->q_count    = htons( 1 );           /* one query */
+  pDNShdr->rr_count   = 0;                    /* none in query */
+  pDNShdr->auth_count = 0;                    /* none in query */
+  pDNShdr->add_count  = 0;                    /* none in query */
+  
+  queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
+  queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
+#ifdef DEBUG
+  fprintf(stderr, "send_DNS_Addr: query=%s, queryLen=%d\n", query, queryLen);
+#endif
+  
+  
+  pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
+  pDNS_qtail->qtype = htons(255);/*htons(DNS_RRTYPE_A); */
+  pDNS_qtail->qclass = htons(DNS_RRCLASS_IN); 
+  queryLen +=  DNS_QTAIL_LEN;
+  
+  /**************************
+   * Send DNS Query Message *
+   **************************/
+  
+
+  res = sendto( commSock,
+               buffer,
+               queryLen,
+               0,
+               (struct sockaddr *) &sockAddr,
+               sizeof( SOCKADDR_IN ) );
+  
+  /*dumpSbuffer(buffer,queryLen);*/
+
+  if ( res < 0 )
+    {
+#ifdef DEBUG
+      fprintf(stderr, "send_DNS_Addr_Query: error %d, errno %d\n", res, errno);
+      fprintf(stderr, "sendto() failed \n");
+#endif
+      return ( -1 );
+    }
+  else
+    {
+    /*printf( "sendto() succeeded\n");*/
+    ;
+    } /* end if */
+  
+  return(0);
+}
+
+
+int send_DNS_AFSDB_Query(char* query, 
+                        SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
+{
+  /*static char buffer[BUFSIZE];*/
+
+  PDNS_HDR    pDNShdr;
+  PDNS_QTAIL  pDNS_qtail;
+
+  int     queryLen = 0;
+  int     res;
+
+#ifndef WIN32_LEAN_AND_MEAN
+  bzero(buffer,BUFSIZE);
+#endif /*WIN32_LEAN_AND_MEAN*/
+
+  /***************************
+   * Build DNS Query Message *
+   *                         *
+   * hard-coded AFSDB query  *
+   ***************************/
+  
+  pDNShdr = (PDNS_HDR)&( buffer[ 0 ] );
+  pDNShdr->id         = htons( 0xDEAD );
+  pDNShdr->flags      = htons( DNS_FLAG_RD ); /* do recurse */
+  pDNShdr->q_count    = htons( 1 );           /* one query */
+  pDNShdr->rr_count   = 0;                    /* none in query */
+  pDNShdr->auth_count = 0;                    /* none in query */
+  pDNShdr->add_count  = 0;                    /* none in query */
+  
+  queryLen = putQName( query, &(buffer[ DNS_HDR_LEN ] ) );
+  queryLen += DNS_HDR_LEN; /* query Length is just after the query name and header */
+  
+  
+  pDNS_qtail = (PDNS_QTAIL) &(buffer[ queryLen ]);
+  pDNS_qtail->qtype = htons(DNS_RRTYPE_AFSDB); 
+  pDNS_qtail->qclass = htons(DNS_RRCLASS_IN); 
+  queryLen +=  DNS_QTAIL_LEN;
+  
+  /**************************
+   * Send DNS Query Message *
+   **************************/
+  
+  res = sendto( commSock,
+               buffer,
+               queryLen,
+               0,
+               (struct sockaddr *) &sockAddr,
+               sizeof( SOCKADDR_IN ) );
+  
+  /*dumpSbuffer(buffer,queryLen);*/
+
+  if ( res < 0 )
+    {
+#ifdef DEBUG
+      fprintf(stderr, "send_DNS_AFSDB_Query: error %d, errno %d\n", res, errno);
+      fprintf(stderr,  "sendto() failed \n");
+#endif /* DEBUG */
+      return ( -1 );
+    }
+  else
+    {
+    /*printf( "sendto() succeeded\n");*/
+    ;
+    } /* end if */
+  
+  return(0);
+}
+
+
+PDNS_HDR get_DNS_Response(SOCKET commSock, SOCKADDR_IN sockAddr, char *buffer)
+{
+  /*static char buffer[BUFSIZE];*/
+
+  int         addrLen = sizeof(SOCKADDR_IN);
+  int         res;
+  int size;
+
+#ifndef WIN32_LEAN_AND_MEAN
+  bzero(buffer,BUFSIZE);
+#endif /*WIN32_LEAN_AND_MEAN*/
+
+  /*****************************
+   * Receive DNS Reply Message *
+   *****************************/
+  
+  /*printf( "calling recvfrom() on connected UDP socket\n" );*/
+  
+  size = recvfrom( commSock,
+                 buffer,
+                 BUFSIZE,
+                 0,
+                 (struct sockaddr *) &sockAddr,
+                 &addrLen );
+  if (size < 0) { fprintf(stderr, "recvfrom error %d\n", errno); return NULL; }
+
+  /*dumpRbuffer(buffer,res);*/
+
+#ifdef DEBUG
+  fprintf(stderr, "recvfrom returned %d bytes from %s: \n", 
+         size, inet_ntoa( sockAddr.sin_addr ) );
+#endif /* DEBUG */
+  
+  return((PDNS_HDR)&( buffer[ 0 ] ));
+
+}
+
+
+int putQName( char *pHostName, char *pQName )
+{
+  int     i;
+  char    c;
+  int     j = 0;
+  int     k = 0;
+  
+  DNSlowerCase(pHostName);
+  /*printf( "Hostname: [%s]\n", pHostName );*/
+  
+  for ( i = 0; *( pHostName + i ); i++ )
+    {
+      c = *( pHostName + i );   /* get next character */
+      
+      
+      if ( c == '.' )
+       {
+         /* dot encountered, fill in previous length */
+         if (k!=0){ /*don't process repeated dots*/
+          /*printf( "%c", c );*/
+           *( pQName + j ) = k;
+           j = j+k+1;  /* set index to next counter */
+           k = 0;      /* reset segment length */
+         }
+       }
+      else
+       {
+        /*printf( "%c", c );*/
+         *( pQName + j + k + 1 ) = c;  /* assign to QName */
+         k++;                /* inc count of seg chars */
+       } /* end if */
+    } /* end for loop */
+  
+  *(pQName + j )                  = k;   /* count for final segment */
+
+  *(pQName + j + k + 1 )      = 0;   /* count for trailing NULL segment is 0 */
+  
+  /*printf( "\n" ); */
+  
+  if (c == '.')
+    return ( j + k + 1 );        /* return total length of QName */
+  else
+    return ( j + k + 2 );
+} /* end putQName() */
+
+
+u_char * skipRRQName(u_char *pQName)
+{
+  u_char *ptr;
+  u_char c;
+
+  ptr = pQName;
+  c = *ptr;
+  while (c) {
+    if ( c >= 0xC0 ) {
+    /* skip the 'compression' pointer */
+      ptr = ptr+1;
+      c = '\0';
+    } else {
+      /* skip a normal qname segment */
+      ptr += *ptr;
+      ptr++;
+      c = *ptr;
+    };
+  };
+
+  /* ptr now pointing at terminating zero of query QName,
+     or the pointer for the previous occurrence 
+     (compression)
+   */
+  ptr++;
+
+  return (ptr);
+} /* end skipRRQName() */
+
+
+
+u_char * printRRQName( u_char *pQName, PDNS_HDR buffer )
+{
+  u_short i, k;
+  u_char *buffPtr = (u_char *) buffer;
+  u_char *namePtr;
+  u_char *retPtr;
+  u_char c;
+
+
+  namePtr = pQName;
+  retPtr = 0;
+
+  for ( i = 0; i < BUFSIZE; i++ )
+    {
+      c = *namePtr;
+      if ( c >= 0xC0 ) {
+       c = *(namePtr + 1);
+       retPtr = namePtr+2;
+       namePtr = buffPtr+c; 
+      } else {
+       if ( c == 0 )
+         break;
+       
+       for ( k = 1; k <= c; k++ )
+         {
+           fprintf(stderr, "%c", *( namePtr + k ) );
+         } /* end for loop */
+       fprintf(stderr,".");
+       namePtr += k;
+      }
+    } /* end for loop */
+  fprintf(stderr,"\n");
+  namePtr++; /* skip terminating zero */
+
+  if (retPtr)
+    return(retPtr);
+  else
+    return(namePtr);
+
+} /* end printRRQName() */
+
+
+u_char * sPrintRRQName( u_char *pQName, PDNS_HDR buffer, char *str )
+{
+  u_short i, k;
+  u_char *buffPtr = (u_char *) buffer;
+  u_char *namePtr;
+  u_char *retPtr;
+  u_char c;
+
+  char   section[64];
+
+  strcpy(str,"");
+  namePtr = pQName;
+  retPtr = 0;
+
+  for ( i = 0; i < BUFSIZE; i++ )
+    {
+      c = *namePtr;
+      if ( c >= 0xC0 ) {
+       c = *(namePtr + 1);
+       retPtr = namePtr+2;
+       namePtr = buffPtr+c; 
+      } else {
+       if ( c == 0 )
+         break;
+       
+       for ( k = 1; k <= c; k++ )
+         {
+           sprintf(section,"%c", *( namePtr + k ) );
+           strcat(str,section);
+         } /* end for loop */
+       strcat(str,".");
+       namePtr += k;
+      }
+    } /* end for loop */
+  namePtr++; /* skip terminating zero */
+
+  if (retPtr)
+    return(retPtr);
+  else
+    return(namePtr);
+
+} /* end sPrintRRQName() */
+
+
+void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
+{
+  u_char *ptr = (u_char *) replyBuff;
+  int    answerCount = ntohs((replyBuff)->rr_count);
+  u_char i;
+  PDNS_AFSDB_RR_HDR 
+         rrPtr;
+
+  ptr += DNS_HDR_LEN;
+
+  /* ptr now pointing at start of QName in query field */
+  ptr = skipRRQName(ptr);
+
+
+  /* skip the query type and class fields */
+  ptr+= DNS_QTAIL_LEN;
+
+  /* ptr should now be at the start of the answer RR sections */
+
+  fprintf(stderr,"---------------------------------\n");
+  for (i=0; i<answerCount ; i++){
+    ptr = skipRRQName(ptr);
+    rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
+    ptr+= DNS_AFSDB_RR_HDR_LEN;
+    if ( ntohs(rrPtr->rr_afsdb_class) == 1) {
+      fprintf(stderr,"AFDB class %d ->  ",ntohs(rrPtr->rr_afsdb_class)); 
+      ptr = printRRQName(ptr,replyBuff); }
+    else
+      ptr = skipRRQName(ptr);
+  };
+  fprintf(stderr,"---------------------------------\n");
+
+
+};
+
+void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHosts, int *numServers, int *ttl)
+  /*PAFS_SRV_LIST (srvList)*/
+{
+  u_char *ptr = (u_char *) replyBuff;
+  int    answerCount = ntohs((replyBuff)->rr_count);
+  u_char i;
+  PDNS_AFSDB_RR_HDR 
+         rrPtr;
+  int srvCount = 0;
+  char hostName[256];
+  struct in_addr addr;
+  int rc;
+
+  ptr += DNS_HDR_LEN;
+
+  /* ptr now pointing at start of QName in query field */
+  ptr = skipRRQName(ptr);
+
+
+  /* skip the query type and class fields */
+  ptr+= DNS_QTAIL_LEN;
+
+  /* ptr should now be at the start of the answer RR sections */
+
+  answerCount = MIN(answerCount, AFSMAXCELLHOSTS);
+#ifdef DEBUG
+  fprintf(stderr, "processRep_AFSDB: answerCount=%d\n", answerCount);
+#endif /* DEBUG */
+
+  for (i=0; i<answerCount ; i++){
+    ptr = skipRRQName(ptr);
+    rrPtr = (PDNS_AFSDB_RR_HDR) ptr;
+    ptr+= DNS_AFSDB_RR_HDR_LEN;
+    if ((ntohs(rrPtr->rr_afsdb_class) == 1) && 
+       (srvCount < MAX_AFS_SRVS)) {
+      /*ptr = sPrintRRQName(ptr,replyBuff,srvList->host[srvList->count]);*/
+      ptr = sPrintRRQName(ptr,replyBuff,hostName);
+      /*ptr = printRRQName(ptr,replyBuff);*/
+      *ttl = ntohl(rrPtr->rr_ttl);
+
+#ifdef DEBUG
+      fprintf(stderr, "resolving name %s\n", hostName);
+#endif
+      /* resolve name from DNS query */
+      rc = DNSgetAddr(commSock, hostName, &addr);
+      if (rc < 0)
+       continue;  /* skip this entry */
+#ifdef DEBUG
+      fprintf(stderr, "processRep_AFSDB: resolved name %s to addr %x\n", hostName, addr);
+#endif /* DEBUG */
+      memcpy(&cellHosts[srvCount], &addr.s_addr, sizeof(addr.s_addr));
+      srvCount++;
+    }
+    else {
+      ptr = skipRRQName(ptr);
+    }
+  }
+
+  *numServers = srvCount;
+
+}
+
+
+u_char * processReplyBuffer_Addr(PDNS_HDR replyBuff)
+{
+  u_char *ptr = (u_char *) replyBuff;
+  int    answerCount = ntohs((replyBuff)->rr_count);
+  u_char i;
+  PDNS_A_RR_HDR 
+         rrPtr;
+
+#ifdef DEBUG
+  fprintf(stderr, "processReplyBuffer_Addr: answerCount=%d\n", answerCount);
+#endif /* DEBUG */
+  if (answerCount == 0) return 0;
+  
+  ptr += DNS_HDR_LEN;
+
+  /* ptr now pointing at start of QName in query field */
+  ptr = skipRRQName(ptr);
+
+
+  /* skip the query type and class fields */
+  ptr+= DNS_QTAIL_LEN;
+
+  /* ptr should now be at the start of the answer RR sections */
+  ptr = skipRRQName(ptr);
+  rrPtr = (PDNS_A_RR_HDR) ptr;
+
+#ifdef DEBUG
+  fprintf(stderr, "type:%d, class:%d, ttl:%d, rdlength:%d\n",
+        ntohs(rrPtr->rr_type),ntohs(rrPtr->rr_class),
+        ntohl(rrPtr->rr_ttl),ntohs(rrPtr->rr_rdlength));
+  fprintf(stderr, "Count %d\tand Answer %8x\n",answerCount,rrPtr->rr_addr);
+#endif /* DEBUG */
+
+  ptr += DNS_A_RR_HDR_LEN;
+
+  return (ptr);
+
+};
+
+int getAFSServer(char *cellName, int *cellHosts, int *numServers, int *ttl)
+{
+  /*static AFS_SRV_LIST srvList;  
+    static int ans = 0;*/
+  SOCKET commSock;
+  SOCKADDR_IN sockAddr;
+  PDNS_HDR  pDNShdr;
+  char buffer[BUFSIZE];
+  int rc;
+
+#ifdef DEBUG
+  fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
+#endif
+
+  if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
+    cm_InitDNS(1);    /* assume enabled */
+  }
+  if (cm_dnsEnabled == 0) {  /* possibly we failed in cm_InitDNS above */
+    fprintf(stderr, "DNS initialization failed, disabled\n");
+    *numServers = 0;
+    return -1;
+  }
+  
+  sockAddr = setSockAddr(dns_addr, DNS_PORT);
+  
+  commSock = socket( AF_INET, SOCK_DGRAM, 0 );
+  if ( commSock < 0 )
+    {
+      /*afsi_log("socket() failed\n");*/
+      fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
+      *numServers = 0;
+      return (-1);
+    } 
+  
+#ifdef DJGPP
+  /* the win95 sock.vxd will not allow sendto for unbound sockets, 
+   *   so just bind to nothing and it works */
+  
+  __djgpp_set_socket_blocking_mode(commSock, 0);
+  bind(commSock,0,sizeof( SOCKADDR_IN ) );
+#endif /* DJGPP */
+
+  rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
+  if (rc < 0) {
+    fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
+    *numServers = 0;
+    return -1;
+  }
+    
+  pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
+  
+  /*printReplyBuffer_AFSDB(pDNShdr);*/
+  if (pDNShdr)
+    processReplyBuffer_AFSDB(commSock, pDNShdr, cellHosts, numServers, ttl);
+  else
+    *numServers = 0;
+  
+  close(commSock);
+  if (*numServers == 0)
+    return(-1);
+
+  else
+    return 0;
+}
+
+int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
+{
+  /* Variables for DNS message parsing and creation */
+  PDNS_HDR  pDNShdr;
+
+  SOCKADDR_IN sockAddr;
+  char buffer[BUFSIZE];
+  
+  int     i;
+  u_char *addr;
+  u_long *aPtr;
+  int rc;
+
+  /**********************
+   * Get a DGRAM socket *
+   **********************/
+  
+  sockAddr = setSockAddr(dns_addr, DNS_PORT);
+  
+  rc = send_DNS_Addr_Query(hostName,commSock,sockAddr, buffer);
+  if (rc < 0) return rc;
+  pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
+  if (pDNShdr == NULL)
+    return -1;
+  
+  addr = processReplyBuffer_Addr(pDNShdr);
+  if (addr == 0)
+    return -1;
+
+  aPtr = (u_long *) addr;
+
+  iNet->s_addr = *aPtr;
+
+  return(0);
+}
+
+#endif /* AFS_AFSDB_ENV */
diff --git a/src/WINNT/afsd/cm_dns.h b/src/WINNT/afsd/cm_dns.h
new file mode 100644 (file)
index 0000000..1e5d28c
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Well-known DNS port is 53 (for both TCP and UDP,
+   although UDP is typically the only one used) */
+
+#define DNS_PORT    53
+
+/* this function will continue to return cell server
+   names for the given cell, ending in null */
+int getAFSServer(char *cellname, int *cellHosts, int *numServers, int *ttl);
+
+/* a supplement for the DJGPP gethostbyname ... which 
+   never bothers calling a DNS server ... so this function
+   takes care of that. This should be called when you
+   failed with gethostbyname (as that WILL check for
+   dotted decimal, and local hostfile) */
+
+struct hostent *DNSgetHostByName(char *hostname);
+
+
+
diff --git a/src/WINNT/afsd/cm_dns_private.h b/src/WINNT/afsd/cm_dns_private.h
new file mode 100644 (file)
index 0000000..1344fe0
--- /dev/null
@@ -0,0 +1,217 @@
+/* Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef __DNS_AFS_private_h_env_
+#define __DNS_AFS_private_h_env_
+
+#ifdef DJGPP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+/*#else
+  #include <windows.h>*/
+#endif
+
+#ifdef KERNEL
+#define SOCKET struct osi_socket *
+#else
+#define SOCKET int
+#endif
+
+#define SOCKADDR_IN struct sockaddr_in
+
+#include <stdio.h>
+#include <string.h>
+
+
+#ifdef DJGPP
+
+char *inet_ntoa(struct in_addr in)
+{
+  static char   out[256];
+  char temp[20];
+  unsigned long sVal,pVal;
+
+  out[0] = '\0';
+
+
+  pVal = ntohl(in.s_addr);
+
+  sVal = pVal;
+  sVal >>= 24;
+  sprintf(out,"%ld",sVal);
+
+  sVal = pVal;
+  sVal <<= 8;
+  sVal >>= 24;
+  sprintf(out,"%s.%ld",out,sVal);
+
+  sVal = pVal;
+  sVal <<= 16;
+  sVal >>= 24;
+  sprintf(out,"%s.%ld",out,sVal);
+
+  sVal = pVal;
+  sVal <<= 24;
+  sVal >>= 24;
+  sprintf(out,"%s.%ld",out,sVal);
+
+  return(&out[0]);
+}
+
+unsigned long inet_addr(const char *cp)
+{
+  
+  unsigned long val=0;
+  unsigned char sVal;
+  
+  char   cp2[256];
+
+  char*  ptr = cp2;
+  int    i;
+  int    len;
+
+  strcpy(cp2,cp);
+
+  for (i=0; i<=strlen(cp); i++)
+    {
+      if (cp2[i] == '.')
+       {
+         cp2[i] = '\0';
+         sVal = atoi(ptr);
+         ptr = &cp2[i+1];
+         val = val << 8;
+         val &= 0xffffff00;
+         val |= sVal;
+         //printf("%x\t%lx\n",sVal,val);
+       };
+    };
+  sVal = atoi(ptr);
+  val = val << 8;
+  val &= 0xffffff00;
+  val |= sVal;
+  //printf("%x\t%lx\n",sVal,val);
+  
+  return htonl(val);
+}
+
+#endif /* DJGPP */
+
+#define BUFSIZE                 2048
+
+/*
+ * AFS Server List (a list of host names and their count)
+ */
+#define MAX_AFS_SRVS 20
+typedef struct afs_srvlist
+{
+  unsigned short  count;           /* number of host names */
+  char     host[MAX_AFS_SRVS][256];/* array of hosts*/
+} AFS_SRV_LIST, *PAFS_SRV_LIST;
+
+
+/*
+ * DNS Message Header
+ */
+typedef struct dns_hdr
+{
+  unsigned short id;          /* client query ID number */
+  unsigned short flags;       /* qualify contents <see below> */
+  unsigned short q_count;     /* number of questions */
+  unsigned short rr_count;    /* number of answer RRs */
+  unsigned short auth_count;  /* number of authority RRs */
+  unsigned short add_count;   /* number of additional RRs */
+} DNS_HDR, *PDNS_HDR;
+
+#define DNS_HDR_LEN sizeof(DNS_HDR)
+
+
+
+/* THESE WERE ALSO WRONG !!!! */
+#define DNS_FLAG_RD 0x0100
+
+/*
+ * DNS query class and response type for the tail of the query packet
+ */
+typedef struct dns_qtail
+{
+        unsigned short qtype;                /* Query type (2bytes) - for responses */
+        unsigned short qclass;               /* Query Class (2bytes) - for questions */
+} DNS_QTAIL, *PDNS_QTAIL;
+
+#define DNS_QTAIL_LEN sizeof(DNS_QTAIL)
+
+/* DNS Generic Resource Record format (from RFC 1034 and 1035)
+ *
+ *  NOTE: The first field in the DNS RR Record header is always
+ *   the domain name in QNAME format (see earlier description)
+ */
+typedef struct dns_rr_hdr
+{
+        unsigned short rr_type;        /* RR type code (e.g. A, MX, NS, etc.) */
+        unsigned short rr_class;       /* RR class code (IN for Internet) */
+        unsigned long  rr_ttl;         /* Time-to-live for resource */
+        unsigned short rr_rdlength;    /* length of RDATA field (in octets) */
+} DNS_RR_HDR, *PDNS_RR_HDR;
+
+#define DNS_RR_HDR_LEN sizeof(DNS_RR_HDR)
+
+#define DNS_RRTYPE_A     1
+#define DNS_RRTYPE_NS    2
+#define DNS_RRTYPE_CNAME 5
+#define DNS_RRTYPE_SOA   6
+#define DNS_RRTYPE_WKS   11
+#define DNS_RRTYPE_PTR   12
+#define DNS_RRTYPE_HINFO 13
+#define DNS_RRTYPE_MX    15
+#define DNS_RRTYPE_AFSDB 18
+
+
+#define DNS_RRCLASS_IN    1    // Internet
+#define DNS_RRCLASS_CS    2    // CSNET
+#define DNS_RRCLASS_CH    3    // CHAOS Net
+#define DNS_RRCLASS_HS    4    // Hesiod
+#define DNS_RRCLASS_WILD  255  // WildCard - all classes
+
+/* 
+ * DNS AFSDB Resource Data Field
+ */
+typedef struct dns_afsdb_rr_hdr
+{
+  unsigned short rr_type;        /* RR type code (e.g. A, MX, NS, etc.) */
+  unsigned short rr_class;       /* RR class code (IN for Internet) */
+  unsigned long  rr_ttl;         /* Time-to-live for resource */
+  unsigned short rr_rdlength;    /* length of RDATA field (in octets) */
+  unsigned short rr_afsdb_class; /* 1-AFS , 2-DCE */
+} DNS_AFSDB_RR_HDR, *PDNS_AFSDB_RR_HDR;
+
+#define DNS_AFSDB_RR_HDR_LEN sizeof(DNS_AFSDB_RR_HDR)
+
+/* 
+ * DNS A Resource Data Field
+ */
+typedef struct dns_a_rr_hdr
+{
+  unsigned short rr_type;        /* RR type code (e.g. A, MX, NS, etc.) */
+  unsigned short rr_class;       /* RR class code (IN for Internet) */
+  unsigned long  rr_ttl;         /* Time-to-live for resource */
+  unsigned short rr_rdlength;    /* length of RDATA field (in octets) */
+  unsigned long  rr_addr;        /* Resolved host address */
+} DNS_A_RR_HDR, *PDNS_A_RR_HDR;
+
+#define DNS_A_RR_LEN      14 //sizeof(DNS_A_RR_HDR)
+#define DNS_A_RR_HDR_LEN  10 //(DNS_A_RR_LEN - sizeof(unsigned long))
+
+int  putQName( char *pszHostName, char *pQName );
+unsigned char * printRRQName( unsigned char *pQName, PDNS_HDR buffer );
+unsigned char * skipRRQName(unsigned char *pQName);
+/* void printReplyBuffer_AFSDB(PDNS_HDR replyBuff); */
+
+#endif //__DNS_AFS_private_h_env_
+
diff --git a/src/WINNT/afsd/cm_freelance.c b/src/WINNT/afsd/cm_freelance.c
new file mode 100644 (file)
index 0000000..6ae0889
--- /dev/null
@@ -0,0 +1,525 @@
+#include <afs/param.h>
+#include <afs/stds.h>
+
+#ifndef DJGPP
+#include <windows.h>
+#include <winsock2.h>
+#else
+#include <netdb.h>
+#endif /* !DJGPP */
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+#include <rx/rx.h>
+
+#include "afsd.h"
+#ifdef AFS_FREELANCE_CLIENT
+#include "cm_freelance.h"
+#include "stdio.h"
+
+int cm_noLocalMountPoints;
+int cm_fakeDirSize;
+int cm_fakeDirCallback=0;
+int cm_fakeGettingCallback=0;
+int cm_fakeDirVersion = 0x8;
+cm_localMountPoint_t* cm_localMountPoints;
+osi_mutex_t cm_Freelance_Lock;
+int cm_localMountPointChangeFlag = 0;
+int cm_freelanceEnabled = 0;
+
+void cm_InitFakeRootDir();
+
+void cm_InitFreelance() {
+  
+       lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
+  
+       // yj: first we make a call to cm_initLocalMountPoints
+       // to read all the local mount points from an ini file
+       cm_InitLocalMountPoints();
+       
+       // then we make a call to InitFakeRootDir to create
+       // a fake root directory based on the local mount points
+       cm_InitFakeRootDir();
+
+       // --- end of yj code
+}
+
+/* yj: Initialization of the fake root directory */
+/* to be called while holding freelance lock unless during init. */
+void cm_InitFakeRootDir() {
+       
+       int i, j, t1, t2;
+       char* currentPos;
+       int noChunks;
+       char mask;
+       
+
+       // allocate space for the fake info
+       cm_dirHeader_t fakeDirHeader;
+       cm_dirEntry_t fakeEntry;
+       cm_pageHeader_t fakePageHeader;
+
+       // i'm going to calculate how much space is needed for
+       // this fake root directory. we have these rules:
+       // 1. there are cm_noLocalMountPoints number of entries
+       // 2. each page is CM_DIR_PAGESIZE in size
+       // 3. the first 13 chunks of the first page are used for
+       //    some header stuff
+       // 4. the first chunk of all subsequent pages are used
+       //    for page header stuff
+       // 5. a max of CM_DIR_EPP entries are allowed per page
+       // 6. each entry takes 1 or more chunks, depending on 
+       //    the size of the mount point string, as determined
+       //    by cm_NameEntries
+       // 7. each chunk is CM_DIR_CHUNKSIZE bytes
+
+       int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
+       int curChunk = 13;      // chunks 0 - 12 are used for header stuff
+                                               // of the first page in the directory
+       int curPage = 0;
+       int curDirEntry = 0;
+       int curDirEntryInPage = 0;
+       int sizeOfCurEntry;
+       int dirSize;
+       
+
+       while (curDirEntry!=cm_noLocalMountPoints) {
+               sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
+               if ((curChunk + sizeOfCurEntry >= CPP) ||
+                       (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
+                       curPage++;
+                       curDirEntryInPage = 0;
+                       curChunk = 0;
+               }
+               curChunk += sizeOfCurEntry;
+               curDirEntry++;
+               curDirEntryInPage++;
+       }
+
+       dirSize = (curPage+1) *  CM_DIR_PAGESIZE;
+       cm_FakeRootDir = malloc(dirSize);
+       cm_fakeDirSize = dirSize;
+
+       
+
+       // yj: when we get here, we've figured out how much memory we need and 
+       // allocated the appropriate space for it. we now prceed to fill
+       // it up with entries.
+       curPage = 0;
+       curDirEntry = 0;
+       curDirEntryInPage = 0;
+       curChunk = 0;
+       
+       // fields in the directory entry that are unused.
+       fakeEntry.flag = 1;
+       fakeEntry.length = 0;
+       fakeEntry.next = 0;
+       fakeEntry.fid.unique = htonl(1);
+
+       // the first page is special, it uses fakeDirHeader instead of fakePageHeader
+       // we fill up the page with dirEntries that belong there and we make changes
+       // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
+       // filling up the dirEntries in this page, we copy the fakeDirHeader into 
+       // the top of the page.
+
+       // init the freeBitmap array
+       for (i=0; i<8; i++) 
+               fakeDirHeader.header.freeBitmap[i]=0;
+
+       fakeDirHeader.header.freeBitmap[0] = 0xff;
+       fakeDirHeader.header.freeBitmap[1] = 0x7f;
+       
+
+       // we start counting at 13 because the 0th to 12th chunks are used for header
+       curChunk = 13;
+
+       // stick the first 2 entries "." and ".." in
+       fakeEntry.fid.unique = htonl(1);
+       fakeEntry.fid.vnode = htonl(1);
+       strcpy(fakeEntry.name, ".");
+       currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
+       memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
+       curChunk++; curDirEntryInPage++;
+       strcpy(fakeEntry.name, "..");
+       currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
+       memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
+       curChunk++; curDirEntryInPage++;
+
+       // keep putting stuff into page 0 if
+       // 1. we're not done with all entries
+       // 2. we have less than CM_DIR_EPP entries in page 0
+       // 3. we're not out of chunks in page 0
+
+       while( (curDirEntry!=cm_noLocalMountPoints) && 
+                  (curDirEntryInPage < CM_DIR_EPP) &&
+                  (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP)) 
+       {
+
+               noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
+               fakeEntry.fid.vnode = htonl(curDirEntry + 2);
+               currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
+
+               memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
+               strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
+               curDirEntry++;
+               curDirEntryInPage++;
+               for (i=0; i<noChunks; i++) {
+                       t1 = (curChunk + i) / 8;
+                       t2 = curChunk + i - (t1*8);
+                       fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
+               }
+               curChunk+=noChunks;
+       }
+
+       // when we get here, we're done with filling in the entries for page 0
+       // copy in the header info
+
+       memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
+
+       curPage++;
+
+       // ok, page 0's done. Move on to the next page.
+       while (curDirEntry!=cm_noLocalMountPoints) {
+               // setup a new page
+               curChunk = 1;                   // the zeroth chunk is reserved for page header
+               curDirEntryInPage = 0; 
+               for (i=0; i<8; i++) {
+                       fakePageHeader.freeBitmap[i]=0;
+               }
+               fakePageHeader.freeCount = 0;
+               fakePageHeader.pgcount = 0;
+               fakePageHeader.tag = htons(1234);
+               
+               // while we're on the same page...
+               while ( (curDirEntry!=cm_noLocalMountPoints) &&
+                               (curDirEntryInPage < CM_DIR_EPP) &&
+                           (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
+               {
+                       // add an entry to this page
+
+                       noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
+                       fakeEntry.fid.vnode=htonl(curDirEntry+2);
+                       currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
+                       memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
+                       strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
+                       curDirEntry++;
+                       curDirEntryInPage++;
+                       for (i=0; i<noChunks; i++) {
+                               t1 = (curChunk + i) / 8;
+                               t2 = curChunk + i - (t1*8);
+                               fakePageHeader.freeBitmap[t1] |= (1 << t2);
+                       }
+                       curChunk+=noChunks;
+               }
+               memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
+
+               curPage++;
+       }
+       
+       // we know the fakeDir is setup properly, so we claim that we have callback
+       cm_fakeDirCallback=1;
+
+       // when we get here, we've set up everything! done!
+
+
+}
+
+int cm_FakeRootFid(cm_fid_t *fidp)
+{
+  fidp->cell = 0x1;            /* root cell */
+       fidp->volume = 0x20000001;   /* root.afs ? */
+       fidp->vnode = 0x1;
+       fidp->unique = 0x1;
+}
+  
+int cm_getLocalMountPointChange() {
+  return cm_localMountPointChangeFlag;
+}
+
+int cm_clearLocalMountPointChange() {
+  cm_localMountPointChangeFlag = 0;
+}
+
+/* called directly from ioctl */
+/* called while not holding freelance lock */
+int cm_noteLocalMountPointChange() {
+  lock_ObtainMutex(&cm_Freelance_Lock);
+  cm_fakeDirVersion++;
+  cm_localMountPointChangeFlag = 1;
+  lock_ReleaseMutex(&cm_Freelance_Lock);
+  return 1;
+}
+
+int cm_reInitLocalMountPoints() {
+       cm_fid_t aFid;
+       int i, j, hash;
+       cm_scache_t *scp, **lscpp, *tscp;
+
+       
+       printf("\n\n----- reinitialization starts ----- \n");
+
+
+       // first we invalidate all the SCPs that were created
+       // for the local mount points
+
+       printf("Invalidating local mount point scp...  ");
+
+       aFid.cell = 0x1;
+       aFid.volume=0x20000001;
+       aFid.unique=0x1;
+       aFid.vnode=0x2;
+
+       lock_ObtainWrite(&cm_scacheLock);
+       lock_ObtainMutex(&cm_Freelance_Lock);  /* always scache then freelance lock */
+       for (i=0; i<cm_noLocalMountPoints; i++) {
+               hash = CM_SCACHE_HASH(&aFid);
+               for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
+                       if (scp->fid.volume == aFid.volume &&
+                               scp->fid.vnode == aFid.vnode &&
+                               scp->fid.unique == aFid.unique 
+                               ) {
+
+                               // mark the scp to be reused
+                               lock_ReleaseWrite(&cm_scacheLock);
+                               lock_ObtainMutex(&scp->mx);
+                               cm_DiscardSCache(scp);
+                               lock_ReleaseMutex(&scp->mx);
+                               cm_CallbackNotifyChange(scp);
+                               lock_ObtainWrite(&cm_scacheLock);
+                               scp->refCount--;
+
+                               // take the scp out of the hash
+                               lscpp = &cm_hashTablep[hash];
+                               for (tscp=*lscpp; tscp; lscpp = &tscp->nextp, tscp = *lscpp) {
+                                       if (tscp == scp) break;
+                               }
+                               *lscpp = scp->nextp;
+                               scp->flags &= ~CM_SCACHEFLAG_INHASH;
+
+
+                       }
+               }
+               aFid.vnode = aFid.vnode + 1;
+       }
+       lock_ReleaseWrite(&cm_scacheLock);
+       printf("\tall old scp cleared!\n");
+
+       // we must free the memory that was allocated in the prev
+       // cm_InitLocalMountPoints call
+       printf("Removing old localmountpoints...  ");
+       free(cm_localMountPoints);
+       printf("\tall old localmountpoints cleared!\n");
+
+       // now re-init the localmountpoints
+       printf("Creating new localmountpoints...  ");
+       cm_InitLocalMountPoints();
+       printf("\tcreated new set of localmountpoints!\n");
+       
+       
+       // now we have to free the memory allocated in cm_initfakerootdir
+       printf("Removing old fakedir...  ");
+       free(cm_FakeRootDir);
+       printf("\t\told fakedir removed!\n");
+
+       // then we re-create that dir
+       printf("Creating new fakedir...  ");
+       cm_InitFakeRootDir();
+       printf("\t\tcreated new fakedir!\n");   
+
+       lock_ReleaseMutex(&cm_Freelance_Lock);
+
+       printf("----- reinit complete -----\n\n");
+}
+
+
+// yj: open up the ini file and read all the local mount 
+// points that are stored there. Part of the initialization
+// process for the freelance client.
+/* to be called while holding freelance lock unless during init. */
+long cm_InitLocalMountPoints() {
+       
+       FILE *fp;
+       char line[200];
+       int n, i;
+       char* t;
+       cm_localMountPoint_t* aLocalMountPoint;
+       char hdir[120];
+
+       cm_GetConfigDir(hdir);
+       strcat(hdir, AFS_FREELANCE_INI);
+       // open the ini file for reading
+       fp = fopen(hdir, "r");
+
+       // if we fail to open the file, create an empty one
+       if (!fp) {
+         fp = fopen(hdir, "w");
+         fputs("0\n", fp);
+         fclose(fp);
+         return 0;  /* success */
+       }
+
+       // we successfully opened the file
+#ifdef DEBUG
+       fprintf(stderr, "opened afs_freelance.ini\n");
+#endif
+       
+       // now we read the first line to see how many entries
+       // there are
+       fgets(line, 200, fp);
+
+       // if the line is empty at any point when we're reading
+       // we're screwed. report error and return.
+       if (*line==0) {
+               afsi_log("error occurred while reading afs_freelance.ini");
+               fprintf(stderr, "error occurred while reading afs_freelance.ini");
+               return -1;
+       }
+
+       // get the number of entries there are from the first line
+       // that we read
+       cm_noLocalMountPoints = atoi(line);
+
+       // create space to store the local mount points
+       cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
+       aLocalMountPoint = cm_localMountPoints;
+               
+       // now we read n lines and parse them into local mount points
+       // where n is the number of local mount points there are, as
+       // determined above.
+       // Each line in the ini file represents 1 local mount point and 
+       // is in the format xxx#yyy:zzz, where xxx is the directory
+       // entry name, yyy is the cell name and zzz is the volume name.
+       // #yyy:zzz together make up the mount point.
+       for (i=0; i<cm_noLocalMountPoints; i++) {
+               fgets(line, 200, fp);
+               // check that the line is not empty
+               if (line[0]==0) {
+                       afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
+                       fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
+                       return -1;
+               }
+               // line is not empty, so let's parse it
+               t = strchr(line, '#');
+               // make sure that there is a '#' separator in the line
+               if (!t) {
+                       afsi_log("error occurred while parsing entry in %s: no # separator in line %d", AFS_FREELANCE_INI, i);
+                       fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # separator in line %d", i);
+                       return -1;
+               }
+               aLocalMountPoint->namep=malloc(t-line+1);
+               memcpy(aLocalMountPoint->namep, line, t-line);
+               *(aLocalMountPoint->namep + (t-line)) = 0;
+               aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
+               memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-2);
+               *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-2)) = 0;
+#ifdef DEBUG
+               fprintf(stderr, "found mount point: name %s, string %s\n",
+                       aLocalMountPoint->namep,
+                       aLocalMountPoint->mountPointStringp);
+#endif
+               
+               aLocalMountPoint++;
+
+       }
+       fclose(fp);
+       return 0;
+}
+
+
+int cm_getNoLocalMountPoints() {
+       return cm_noLocalMountPoints;
+}
+
+cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) {
+       return 0;
+}
+
+long cm_FreelanceAddMount(char *filename, char *cellname, char *volume)
+{
+    FILE *fp;
+    char hfile[120];
+    char line[200];
+    int n;
+
+    lock_ObtainMutex(&cm_Freelance_Lock);
+
+     cm_GetConfigDir(hfile);
+     strcat(hfile, AFS_FREELANCE_INI);
+     fp = fopen(hfile, "r+");
+     if (!fp)
+       return CM_ERROR_INVAL;
+     fgets(line, 200, fp);
+     n = atoi(line);
+     n++;
+     fseek(fp, 0, SEEK_SET);
+     fprintf(fp, "%d", n);
+     fseek(fp, 0, SEEK_END);
+     fprintf(fp, "%s#%s:%s\n", filename, cellname, volume);
+     fclose(fp);
+     lock_ReleaseMutex(&cm_Freelance_Lock);
+
+     cm_noteLocalMountPointChange();
+
+     return 0;
+}
+
+long cm_FreelanceRemoveMount(char *toremove)
+{
+     int i, n, t1, t2;
+     char* cp;
+     char line[200];
+     char shortname[200];
+     char hfile[120], hfile2[120];
+     FILE *fp1, *fp2;
+     char cmd[200];
+     int found=0;
+
+    lock_ObtainMutex(&cm_Freelance_Lock);
+
+     cm_GetConfigDir(hfile);
+     strcat(hfile, AFS_FREELANCE_INI);
+     strcpy(hfile2, hfile);
+     strcat(hfile2, "2");
+     fp1=fopen(hfile, "r+");
+     if (!fp1)
+       return CM_ERROR_INVAL;
+     fp2=fopen(hfile2, "w+");
+     if (!fp2) {
+       fclose(fp1);
+       return CM_ERROR_INVAL;
+     }
+
+     fgets(line, 200, fp1);
+     n=atoi(line);
+     fprintf(fp2, "%d\n", n-1);
+
+     for (i=0; i<n; i++) {
+          fgets(line, 200, fp1);
+          cp=strchr(line, '#');
+          memcpy(shortname, line, cp-line);
+          shortname[cp-line]=0;
+
+          if (strcmp(shortname, toremove)==0) {
+
+          } else {
+           found = 1;
+           fputs(line, fp2);
+          }
+     }
+
+     fclose(fp1);
+     fclose(fp2);
+     if (!found)
+       return CM_ERROR_NOSUCHFILE;
+
+     unlink(hfile);
+     rename(hfile2, hfile);
+
+     lock_ReleaseMutex(&cm_Freelance_Lock);
+
+     cm_noteLocalMountPointChange();
+     return 0;
+}
+
+#endif /* AFS_FREELANCE_CLIENT */
diff --git a/src/WINNT/afsd/cm_freelance.h b/src/WINNT/afsd/cm_freelance.h
new file mode 100644 (file)
index 0000000..63cfae5
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _CM_FREELANCE_H
+#define _CM_FREELANCE_H 1
+
+
+typedef struct cm_localMountPoint {
+       char* namep;
+       char* mountPointStringp;
+       struct cm_localMountPoint* next;
+} cm_localMountPoint_t;
+
+extern int cm_getNoLocalMountPoints();
+extern long cm_InitLocalMountPoints();
+extern int cm_getLocalMountPointChange();
+extern int cm_reInitLocalMountPoints();
+extern cm_localMountPoint_t* cm_getLocalMountPoint(int vnode);
+
+#define AFS_FREELANCE_INI "afs_freelance.ini"
+
+#endif // _CM_FREELANCE_H
index 58d8873..eb5a671 100644 (file)
@@ -44,6 +44,9 @@
 #define MAX_PATH 260
 
 osi_mutex_t cm_Afsdsbmt_Lock;
+#ifdef AFS_FREELANCE_CLIENT
+extern osi_mutex_t cm_Freelance_Lock;
+#endif
 
 extern afs_int32 cryptall;
 
@@ -1130,6 +1133,7 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
         char fullCell[256];
        char volume[256];
        char cell[256];
+       int ttl;
 
        cm_InitReq(&req);
         
@@ -1155,7 +1159,11 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
        
                /* Get the full name for this cell */
                code = cm_SearchCellFile(cell, fullCell, 0, 0);
-               if (code)
+#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);
@@ -1164,6 +1172,14 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
                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);
+         return code;
+       }
+#endif
        /* create the symlink with mode 644.  The lack of X bits tells
          * us that it is a mount point.
          */
@@ -1854,9 +1870,9 @@ 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 */
+
index ee5b338..04ba13b 100644 (file)
@@ -125,6 +125,9 @@ extern long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
+extern long cm_IoctlFreemountAddCell(smb_ioctl_t *ioctlp, cm_user_t *userp);
+
+extern long cm_IoctlFreemountRemoveCell(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 #endif /* __CM_IOCTL_INTERFACES_ONLY__ */
 
index 759a31f..d3add60 100644 (file)
@@ -43,6 +43,10 @@ osi_rwlock_t cm_scacheLock;
 /* Dummy scache entry for use with pioctl fids */
 cm_scache_t cm_fakeSCache;
 
+#ifdef AFS_FREELANCE_CLIENT
+extern osi_mutex_t cm_Freelance_Lock;
+#endif
+
 /* must be called with cm_scacheLock write-locked! */
 void cm_AdjustLRU(cm_scache_t *scp)
 {
@@ -236,11 +240,16 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
         long code;
         cm_volume_t *volp;
         cm_cell_t *cellp;
+       char* mp;
+       int special; // yj: boolean variable to test if file is on root.afs
+       int isRoot;
         
         hash = CM_SCACHE_HASH(fidp);
         
        osi_assert(fidp->cell != 0);
 
+       // yj: check if we have the scp, if so, we don't need
+       // to do anything else
         lock_ObtainWrite(&cm_scacheLock);
        for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
                if (cm_FidCmp(fidp, &scp->fid) == 0) {
@@ -252,18 +261,85 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
                 }
         }
         
-        /* otherwise, we need to find the volume */
-        lock_ReleaseWrite(&cm_scacheLock);     /* for perf. reasons */
-        cellp = cm_FindCellByID(fidp->cell);
-        if (!cellp) return CM_ERROR_NOSUCHCELL;
+       // yj: when we get here, it means we don't have an scp
+       // so we need to either load it or fake it, depending
+       // on whether the file is "special", see below.
+
+       // yj: if we're trying to get an scp for a file that's
+       // on root.afs of homecell, we want to handle it specially
+       // because we have to fill in the status stuff 'coz we
+       // don't want trybulkstat to fill it in for us
+#ifdef AFS_FREELANCE_CLIENT
+       special = (fidp->cell==0x1 && fidp->volume==0x20000001 && 
+                          !(fidp->vnode==0x1 && fidp->unique==0x1));
+       isRoot = (fidp->cell==0x1 && fidp->volume==0x20000001 && 
+                          fidp->vnode==0x1 && fidp->unique==0x1);
+       if (cm_freelanceEnabled && isRoot) {
+          /* freelance: if we are trying to get the root scp for the first
+             time, we will just put in a place holder entry. */
+         volp = NULL;
+       }
+         
+       if (cm_freelanceEnabled && special) {
+         /*afsi_log("cm_getscache: special"); */
+               lock_ObtainMutex(&cm_Freelance_Lock);
+               mp =(cm_localMountPoints+fidp->vnode-2)->mountPointStringp;
+               lock_ReleaseMutex(&cm_Freelance_Lock);
+               
+               scp = cm_GetNewSCache();
+               
+               scp->fid = *fidp;
+               scp->volp = cm_rootSCachep->volp;
+               if (scp->dotdotFidp == (cm_fid_t *) NULL)
+                       scp->dotdotFidp = (cm_fid_t *) malloc (sizeof(cm_fid_t));
+               scp->dotdotFidp->cell=0x1;
+               scp->dotdotFidp->volume=0x20000001;
+               scp->dotdotFidp->unique=1;
+               scp->dotdotFidp->vnode=1;
+               scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO);
+               scp->nextp=cm_hashTablep[hash];
+               cm_hashTablep[hash]=scp;
+               scp->flags |= CM_SCACHEFLAG_INHASH;
+               scp->refCount = 1;
+               scp->fileType = CM_SCACHETYPE_MOUNTPOINT;
+
+               lock_ObtainMutex(&cm_Freelance_Lock);
+               scp->length.LowPart = strlen(mp)+4;
+               scp->mountPointStringp=malloc(strlen(mp));
+               strcpy(scp->mountPointStringp,mp);
+               lock_ReleaseMutex(&cm_Freelance_Lock);
+
+               scp->owner=0x0;
+               scp->unixModeBits=0x1ff;
+               scp->clientModTime=0x3b49f6e2;
+               scp->serverModTime=0x3b49f6e2;
+               scp->parentUnique = 0x1;
+               scp->parentVnode=0x1;
+               scp->group=0;
+               scp->dataVersion=0x8;
+               *outScpp = scp;
+               lock_ReleaseWrite(&cm_scacheLock);
+               /*afsi_log("   getscache done");*/
+               return 0;
 
-        code = cm_GetVolumeByID(cellp, fidp->volume, userp, reqp, &volp);
-        if (code) return code;
+       }
+       // end of yj code
+#endif /* AFS_FREELANCE_CLIENT */
+
+        /* otherwise, we need to find the volume */
+       if (!cm_freelanceEnabled || !isRoot) {
+         lock_ReleaseWrite(&cm_scacheLock);    /* for perf. reasons */
+         cellp = cm_FindCellByID(fidp->cell);
+         if (!cellp) return CM_ERROR_NOSUCHCELL;
+
+         code = cm_GetVolumeByID(cellp, fidp->volume, userp, reqp, &volp);
+         if (code) return code;
+          lock_ObtainWrite(&cm_scacheLock);
+       }
         
         /* otherwise, we have the volume, now reverify that the scp doesn't
          * exist, and proceed.
          */
-        lock_ObtainWrite(&cm_scacheLock);
        for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
                if (cm_FidCmp(fidp, &scp->fid) == 0) {
                        scp->refCount++;
@@ -281,20 +357,22 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
        scp->fid = *fidp;
        scp->volp = volp;       /* a held reference */
 
-       /* if this scache entry represents a volume root then we need 
-        * to copy the dotdotFipd from the volume structure where the 
-        * "master" copy is stored (defect 11489)
-        */
-       if(scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) {
-               if (scp->dotdotFidp == (cm_fid_t *) NULL)
-                       scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t));
-               *(scp->dotdotFidp) = *volp->dotdotFidp;
+       if (!cm_freelanceEnabled || !isRoot) {
+         /* if this scache entry represents a volume root then we need 
+          * to copy the dotdotFipd from the volume structure where the 
+          * "master" copy is stored (defect 11489)
+          */
+         if(scp->fid.vnode == 1 && scp->fid.unique == 1 && volp->dotdotFidp) {
+           if (scp->dotdotFidp == (cm_fid_t *) NULL)
+             scp->dotdotFidp = (cm_fid_t *) malloc(sizeof(cm_fid_t));
+           *(scp->dotdotFidp) = *volp->dotdotFidp;
+         }
+         
+         if (volp->roID == fidp->volume)
+           scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO);
+         else if (volp->bkID == fidp->volume)
+           scp->flags |= CM_SCACHEFLAG_RO;
        }
-
-       if (volp->roID == fidp->volume)
-               scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO);
-       else if (volp->bkID == fidp->volume)
-                       scp->flags |= CM_SCACHEFLAG_RO;
        scp->nextp = cm_hashTablep[hash];
        cm_hashTablep[hash] = scp;
         scp->flags |= CM_SCACHEFLAG_INHASH;
@@ -504,7 +582,16 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
                                goto sleep;
                 }
 
-                if (flags & CM_SCACHESYNC_NEEDCALLBACK) {
+               // yj: modified this so that callback only checked if we're
+               // not checking something on /afs
+               if (  (flags & CM_SCACHESYNC_NEEDCALLBACK)
+#ifdef AFS_FREELANCE_CLIENT
+                       && (!cm_freelanceEnabled || !(!(scp->fid.vnode==0x1 &&
+                                                        scp->fid.unique==0x1) &&
+                                                        scp->fid.cell==0x1 &&
+                                                        scp->fid.volume==0x20000001))
+#endif /* AFS_FREELANCE_CLIENT */
+                   ) {
                        if (!cm_HaveCallback(scp)) {
                                osi_Log1(afsd_logp, "CM SyncOp getting callback on scp %x",
                                        (long) scp);
@@ -703,6 +790,31 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags)
 void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp,
        cm_user_t *userp, int flags)
 {
+       // yj: i want to create some fake status for the /afs directory and the
+       // entries under that directory
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled && scp == cm_rootSCachep) {
+               statusp->InterfaceVersion = 0x1;
+               statusp->FileType = 0x2;
+               statusp->LinkCount = scp->linkCount;
+               statusp->Length = cm_fakeDirSize;
+               statusp->DataVersion = cm_fakeDirVersion;
+               statusp->Author = 0x1;
+               statusp->Owner = 0x0;
+               statusp->CallerAccess = 0x9;
+               statusp->AnonymousAccess = 0x9;
+               statusp->UnixModeBits = 0x1ff;
+               statusp->ParentVnode = 0x1;
+               statusp->ParentUnique = 0x1;
+               statusp->SegSize = 0;
+               statusp->ClientModTime = 0x3b49f6e2;
+               statusp->ServerModTime = 0x3b49f6e2;
+               statusp->Group = 0;
+               statusp->SyncCounter = 0;
+               statusp->dataVersionHigh = 0;
+       }
+#endif /* AFS_FREELANCE_CLIENT */
+
        if (!(flags & CM_MERGEFLAG_FORCE)
                        && statusp->DataVersion < (unsigned long) scp->dataVersion) {
                struct cm_cell *cellp;
index 440d34d..e29d89d 100644 (file)
@@ -1059,6 +1059,14 @@ long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp)
         AFSFetchStatus newDirStatus;
         AFSVolSync volSync;
 
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
+         /* deleting a mount point from the root dir. */
+         code = cm_FreelanceRemoveMount(namep);
+         return code;
+       }
+#endif
+
        /* make sure we don't screw up the dir status during the merge */
         lock_ObtainMutex(&dscp->mx);
        sflags = CM_SCACHESYNC_STOREDATA;
@@ -1499,6 +1507,21 @@ long cm_TryBulkProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
                 cm_ReleaseSCache(tscp);
         }      /* found entry */
 
+#ifdef AFS_FREELANCE_CLIENT
+       // yj: if this is a mountpoint under root.afs then we don't want it
+       // to be bulkstat-ed, instead, we call getSCache directly and under
+       // getSCache, it is handled specially.
+       if      (cm_freelanceEnabled &&
+           tfid.cell==0x1 && tfid.volume==0x20000001 &&
+                          !(tfid.vnode==0x1 && tfid.unique==0x1) )
+       {
+#ifdef DEBUG
+               afsi_log("   cm_trybulkproc going to call getscache");
+#endif
+               return cm_GetSCache(&tfid, &tscp, NULL, NULL);
+       }
+#endif /* AFS_FREELANCE_CLIENT */
+
        i = bsp->counter++;
         bsp->fids[i].Volume = scp->fid.volume;
         bsp->fids[i].Vnode = tfid.vnode;
index b0b7bc9..08c2d1e 100644 (file)
@@ -17,3 +17,7 @@ EXPORTS
        cm_AppendNewCell                @10
        cm_AppendNewCellLine            @11
        cm_CloseCellFile                @12
+     cm_SearchCellByDNS       @13
+     getAFSServer             @14
+     cm_InitDNS               @15
+     cm_GetConfigDir          @16
index aaf0c8f..efeb5eb 100644 (file)
@@ -82,8 +82,10 @@ extern void osi_SleepSpin(long value, Crit_Sec *counterp);
 /* spin lock version of wakeup, used internally only */
 extern void osi_WakeupSpin(long value);
 
+#ifndef DJGPP
 /* exported function to sleep on a value */
 extern void osi_Sleep (long);
+#endif
 
 extern void osi_FreeSleepInfo(osi_sleepInfo_t *);
 
index 5d9cb48..5ff836a 100644 (file)
@@ -74,7 +74,8 @@ EXELIBS =\
        $(EXELIBDIR)\afslwp.lib \
        $(EXELIBDIR)\afs\afsutil.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
-       $(EXELIBDIR)\afs\afsreg.lib
+       $(EXELIBDIR)\afs\afsreg.lib \
+       $(DESTDIR)\lib\cm_dns.obj
 
 
 $(SETKEY_EXEFILE): $(SETKEY_EXEOBJS) $(EXELIBS)
index ed47eeb..9eb77da 100644 (file)
@@ -24,6 +24,9 @@ RCSID("$Header$");
 #include <sys/utime.h>
 #include <io.h>
 #include <WINNT/afssw.h>
+#ifdef AFS_AFSDB_ENV
+#include <cm_dns.h>
+#endif /* AFS_AFSDB_ENV */
 #else
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -56,6 +59,7 @@ RCSID("$Header$");
 #include <afs/afsutil.h>
 #include "cellconfig.h"
 #include "keys.h"
+#include <afs/afsint.h>
 
 static ParseHostLine();
 static ParseCellLine();
@@ -364,9 +368,12 @@ char clones[];
 #else
     i = GetCellUnix(adir);
 #endif
+
+#ifndef AFS_FREELANCE_CLIENT  /* no local cell not fatal in freelance */
     if (i) {
        return i;
     }
+#endif
 
     /* now parse the individual lines */
     curEntry = 0;
@@ -564,6 +571,7 @@ afsconf_GetExtendedCellInfo(adir, acellName, aservice, acellInfo, clones)
 }
 
 #ifdef AFS_AFSDB_ENV
+#if !defined(AFS_NT40_ENV)
 afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
     char *acellName;
     char *aservice;
@@ -656,6 +664,58 @@ afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
 
     return 0;
 }
+#else  /* windows */
+int afsconf_GetAfsdbInfo(acellName, aservice, acellInfo)
+  char *aservice;
+  char *acellName;
+  struct afsconf_cell *acellInfo;
+{
+    register afs_int32 i;
+    int tservice;
+    struct afsconf_entry DNSce;
+    char *DNStmpStrp; /* a temp string pointer */
+    struct hostent *thp;
+    afs_int32 cellHosts[AFSMAXCELLHOSTS];
+    int numServers;
+    int rc;
+    int *ttl;
+
+    DNSce.cellInfo.numServers=0;
+    DNSce.next = NULL;
+    rc = getAFSServer(acellName, cellHosts, &numServers, &ttl);
+    /* ignore the ttl here since this code is only called by transitory programs
+       like klog, etc. */
+    if (rc < 0)
+      return -1;
+    if (numServers == 0)
+      return -1;
+
+    for (i = 0; i < numServers; i++)
+    {
+        memcpy(&acellInfo->hostAddr[i].sin_addr.s_addr, &cellHosts[i], sizeof(long));
+        acellInfo->hostAddr[i].sin_family = AF_INET;
+
+        /* sin_port supplied by connection code */
+    }
+
+    acellInfo->numServers = numServers;
+    strcpy(acellInfo->name, acellName);
+    if (aservice) {
+        LOCK_GLOBAL_MUTEX
+        tservice = afsconf_FindService(aservice);
+     UNLOCK_GLOBAL_MUTEX
+        if (tservice < 0) {
+            return AFSCONF_NOTFOUND;  /* service not found */
+     }
+     for(i=0; i< acellInfo->numServers; i++) {
+            acellInfo->hostAddr[i].sin_port = tservice;
+     }
+    }
+    acellInfo->linkedCell = NULL;    /* no linked cell */
+    acellInfo->flags = 0;
+    return 0;
+}
+#endif /* windows */
 #endif /* AFS_AFSDB_ENV */
 
 afsconf_GetCellInfo(adir, acellName, aservice, acellInfo)
index 7206ea9..ddbacc3 100644 (file)
@@ -15,7 +15,7 @@ AFS_OSTYPE = DJGPP
 OPTMZ=-O2
 #PAM_CFLAGS = -O2 -Dlinux -DLINUX_PAM -fPIC
 # Put -O2 here to _ensure_ all Makefiles pick it up.
-XCFLAGS= ${DBG} -Dfds_bits=fd_bits
+XCFLAGS= ${DBG} -Dfds_bits=fd_bits -DAFS_AFSDB_ENV -DAFS_FREELANCE_CLIENT
 MT_CFLAGS=${XCFLAGS}
 XLDFLAGS=
 SHARE_LDFLAGS = -shared -Xlinker -x
index 83cce89..2d48de1 100644 (file)
@@ -152,7 +152,9 @@ afscdefs =\
        -I$(DESTDIR)\include\rx \
        -DWIN32_LEAN_AND_MEAN \
        -DSTRICT \
-       -D_WIN32_IE=0x0400
+       -D_WIN32_IE=0x0400 \
+     -DAFS_AFSDB_ENV \
+     -DAFS_FREELANCE_CLIENT
 
 afscdefs = $(afscdefs) $(AFSDEV_AUXCDEFINES)
 
index 2c31415..176015c 100644 (file)
@@ -164,7 +164,9 @@ afscdefs =\
        -I$(DESTDIR)\include\rx \
        -DWIN32_LEAN_AND_MEAN \
        -DSTRICT \
-       -D_WIN32_IE=0x0400
+       -D_WIN32_IE=0x0400 \
+     -DAFS_AFSDB_ENV \
+     -DAFS_FREELANCE_CLIENT
 
 !      IF ((EXIST($(MSSDK)\include)) && (("$(SYS_NAME)"=="i386_win95" ) || ("$(SYS_NAME)"=="I386_WIN95" )))
 afscdefs=$(afscdefs) -I$(MSSDK)\include $(afscppdefs) \
index 9237e56..6168147 100644 (file)
@@ -194,7 +194,7 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
 #undef HAVE_RES_SEARCH
 //#undef HAVE_SOCKET
 
-#if ENDIANESS_IN_SYS_PARAM_H
+#ifdef ENDIANESS_IN_SYS_PARAM_H
 # ifndef KERNEL
 #  include <sys/types.h>
 #  include <sys/param.h>
@@ -204,7 +204,8 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
 # endif
 #endif
 
-#undef AFS_AFSDB_ENV
+/*#undef AFS_AFSDB_ENV*/
+#define AFS_AFSDB_ENV 1
 #undef AFS_NAMEI_ENV
 #undef BOS_RESTRICTED_MODE
 
index def0154..02577f9 100644 (file)
@@ -94,7 +94,8 @@ AFSLIBS =  \
        $(DESTDIR)\lib\afsrx.lib \
        $(DESTDIR)\lib\afsubik.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
-       $(DESTDIR)\lib\afsrxkad.lib
+       $(DESTDIR)\lib\afsrxkad.lib \
+       $(DESTDIR)\lib\cm_dns.obj
        
 TOKENLIB = $(DESTDIR)\lib\afs\afspioctl.lib
 
index b524cfc..a615470 100644 (file)
@@ -247,8 +247,10 @@ CommandProc (as, arock)
     code = ka_Init(0);
     if (code ||
        !(lcell = ka_LocalCell())) {
+#ifndef AFS_FREELANCE_CLIENT
        if (!Pipe) com_err (rn, code , "Can't get local cell name!");
        exit (1);
+#endif
     }
 
     code = rx_Init(0);
@@ -353,7 +355,15 @@ CommandProc (as, arock)
        memset(as->parms[aNEWPASSWORD].items->data, 0, strlen(as->parms[aNEWPASSWORD].items->data));
     }
 
+#ifdef AFS_FREELANCE_CLIENT
+    if (!foundExplicitCell && !lcell) {
+       if (!Pipe) com_err (rn, code, "no cell name provided");
+        exit(1);
+    }
+#else
     if (!foundExplicitCell) strcpy (realm, lcell);
+#endif /* freelance */
+    
     if (code = ka_CellToRealm (realm, realm, &local)) {
        if (!Pipe) com_err (rn, code, "Can't convert cell to realm");
        exit (1);
index a62e378..c37c66d 100644 (file)
@@ -96,6 +96,7 @@ afs_int32 ka_UserAuthenticateGeneral(
        char fullRealm[256];
        char upperRealm[256];
        struct servent *sp;
+       int ttl;
 
        struct ktc_principal server;
        struct ktc_principal client;
@@ -106,6 +107,11 @@ afs_int32 ka_UserAuthenticateGeneral(
 
        code = cm_SearchCellFile(realm, fullRealm, ka_AddHostProc, NULL);
 
+#ifdef AFS_AFSDB_ENV
+       if (code) {
+         code = cm_SearchCellByDNS(realm, fullRealm, &ttl, ka_AddHostProc, NULL);
+        }
+#endif
        if (code) {
                *reasonP = "specified realm is unknown";
                return (code);
@@ -310,24 +316,27 @@ static check_response
     ptr = (char *) cip->dat + 8;
 
     /* Check and extract server's name */
-    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) {
        return(INTK_BADPW);
+    }
 
     (void) strncpy(s_service, ptr, sizeof(s_service)-1);
     s_service[sizeof(s_service)-1] = '\0';
     ptr += strlen(s_service) + 1;
 
     /* Check and extract server's instance */
-    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) {
        return(INTK_BADPW);
+    }
 
     (void) strncpy(s_instance,ptr, sizeof(s_instance)-1);
     s_instance[sizeof(s_instance)-1] = '\0';
     ptr += strlen(s_instance) + 1;
 
     /* Check and extract server's realm */
-    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+    if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) {
        return(INTK_BADPW);
+    }
 
     (void) strncpy(s_realm,ptr, sizeof(s_realm));
     s_realm[sizeof(s_realm)-1] = '\0';
@@ -340,8 +349,9 @@ static check_response
     ticket_len = (unsigned char) *ptr++;
     
     if ((ticket_len < 0) ||
-       ((ticket_len + (ptr - (char *) cip->dat)) > (int) cip->length))
+       ((ticket_len + (ptr - (char *) cip->dat)) > (int) cip->length)) {
        return(INTK_BADPW);
+    }
 
     /* Check returned server name, instance, and realm fields */
     /*
index 4182a21..c739b87 100644 (file)
@@ -90,6 +90,7 @@ DLLOBJS =\
        $(SYSOBJS) \
        $(WINNTAFSDOBJS) \
        $(AUDITOBJS) \
+       $(DESTDIR)\lib\cm_dns.obj \
        afsauthent.res
 
 audit.obj: $(AUDIT)\audit.c
@@ -231,4 +232,4 @@ install: $(LIBFILE)
 install9x: install
 
 clean ::
-       $(DEL) $(LIBFILE)
\ No newline at end of file
+       $(DEL) $(LIBFILE)
index 02ea656..1e277f0 100644 (file)
@@ -65,7 +65,8 @@ PTSERVER_EXELIBS =\
        $(DESTDIR)\lib\afs\afsutil.lib \
        $(DESTDIR)\lib\afs\afsaudit.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
-       $(DESTDIR)\lib\afs\afsreg.lib
+       $(DESTDIR)\lib\afs\afsreg.lib \
+       $(DESTDIR)\lib\cm_dns.obj
 
 !IF (("$(SYS_NAME)"!="i386_win95" ) && ("$(SYS_NAME)"!="I386_WIN95" ))
 PTSERVER_EXELIBS =$(PTSERVER_EXELIBS) $(DESTDIR)\lib\afs\afsprocmgmt.lib
@@ -100,7 +101,8 @@ PTS_EXELIBS =\
        $(DESTDIR)\lib\afs\afscmd.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afseventlog.lib \
-       $(DESTDIR)\lib\afs\afspioctl.lib
+       $(DESTDIR)\lib\afs\afspioctl.lib \
+       $(DESTDIR)\lib\cm_dns.obj
 
 $(PTS): $(PTS_EXEOBJS) $(PTS_EXELIBS) 
        $(EXECONLINK)
index 7546c9f..b6dce8a 100644 (file)
@@ -833,7 +833,14 @@ int main (argc, argv)
 {
     register afs_int32 code;
     register struct cmd_syndesc *ts;
+#ifdef WIN32
+    WSADATA WSAjunk;
+#endif
 
+#ifdef WIN32
+    WSAStartup(0x0101, &WSAjunk);
+#endif
+    
 #ifdef AFS_AIX32_ENV
     /*
      * The following signal action for AIX is necessary so that in case of a