]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Initial revision
authorSam Hartman <hartmans@debian.org>
Sun, 14 Oct 2001 17:58:46 +0000 (17:58 +0000)
committerSam Hartman <hartmans@debian.org>
Sun, 14 Oct 2001 17:58:46 +0000 (17:58 +0000)
acinclude.m4 [new file with mode: 0644]
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/afs/LINUX/osi_vfs.hin [new file with mode: 0644]
src/afs/afs_dynroot.c [new file with mode: 0644]
src/afs/afs_nfsdisp.c [new file with mode: 0644]

diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644 (file)
index 0000000..5051481
--- /dev/null
@@ -0,0 +1,482 @@
+dnl This file contains the common configuration code which would
+dnl otherwise be duplicated between configure and configure-libafs.
+dnl
+dnl NB: Because this code is a macro, references to positional shell
+dnl parameters must be done like $[]1 instead of $1
+
+AC_DEFUN(OPENAFS_CONFIGURE_COMMON,[
+
+AC_CANONICAL_HOST
+SRCDIR_PARENT=`pwd`
+
+#BOZO_SAVE_CORES BOS_RESTRICTED_MODE BOS_NEW_CONFIG pam sia
+AC_ARG_WITH(afs-sysname,
+[  --with-afs-sysname=sys    use sys for the afs sysname]
+)
+AC_ARG_ENABLE( obsolete,
+[  --enable-obsolete                   enable obsolete portions of AFS (mpp, ntp and package)],, enable_obsolete="no")
+AC_ARG_ENABLE( insecure,
+[  --enable-insecure                   enable insecure portions of AFS (ftpd, inetd, rcp, rlogind and rsh)],, enable_insecure="no")
+AC_ARG_ENABLE( afsdb,
+[  --disable-afsdb                     disable AFSDB RR support],, enable_afsdb="yes")
+AC_ARG_ENABLE( bos-restricted-mode,
+[  --enable-bos-restricted-mode        enable bosserver restricted mode which disables certain bosserver functionality],, enable_bos_restricted_mode="no")
+AC_ARG_ENABLE( namei-fileserver,
+[  --enable-namei-fileserver           force compilation of namei fileserver in preference to inode fileserver],, enable_namei_fileserver="no")
+AC_ARG_ENABLE( fast-restart,
+[  --enable-fast-restart               enable fast startup of file server without salvaging],, enable_fast_restart="no")
+AC_ARG_ENABLE( bitmap-later,
+[  --enable-bitmap-later               enable fast startup of file server by not reading bitmap till needed],, enable_bitmap_later="no")
+AC_ARG_ENABLE( full-vos-listvol-switch,
+[  --enable-full-vos-listvol-switch     enable vos full listvol switch for formatted output],, enable_full_vos_listvol_switch="no")
+AC_ARG_WITH(dux-kernel-headers,
+[  --with-dux-kernel-headers=path      use the kernel headers found at path(optional, defaults to first match in /usr/sys)]
+)
+AC_ARG_WITH(linux-kernel-headers,
+[  --with-linux-kernel-headers=path            use the kernel headers found at path(optional, defaults to /usr/src/linux)]
+)
+AC_ARG_ENABLE(kernel-module,
+[  --disable-kernel-module                     disable compilation of the kernel module (defaults to enabled)],, enable_kernel_module="yes"
+)
+AC_ARG_ENABLE(redhat-buildsys,
+[  --enable-redhat-buildsys            enable compilation of the redhat build system kernel (defaults to disabled)],, enable_redhat_buildsys="no"
+)
+AC_ARG_ENABLE(transarc-paths,
+[  --enable-transarc-paths                     Use Transarc style paths like /usr/afs and /usr/vice],, enable_transarc_paths="no"
+)
+AC_ARG_ENABLE(tivoli-tsm,
+[  --enable-tivoli-tsm                 Enable use of the Tivoli TSM API libraries for butc support],, enable_tivoli_tsm="no"
+)
+
+AC_PROG_CC
+
+dnl weird ass systems
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+
+dnl Various compiler setup.
+AC_C_INLINE
+AC_C_CONST
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SIGNAL
+
+dnl Checks for programs.
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AC_PROG_YACC
+AM_PROG_LEX
+
+OPENAFS_CHECK_BIGENDIAN
+
+AC_MSG_CHECKING(your OS)
+system=$host
+case $system in
+        *-linux*)
+               MKAFS_OSTYPE=LINUX
+               if test "x$enable_redhat_buildsys" = "xyes"; then
+                AC_DEFINE(ENABLE_REDHAT_BUILDSYS)
+               fi
+               if test "x$enable_kernel_module" = "xyes"; then
+                if test "x$with_linux_kernel_headers" != "x"; then
+                  LINUX_KERNEL_PATH="$with_linux_kernel_headers"
+                else
+                  LINUX_KERNEL_PATH="/usr/src/linux"
+                fi
+                if test -f "$LINUX_KERNEL_PATH/include/linux/version.h"; then
+                 linux_kvers=`fgrep UTS_RELEASE $LINUX_KERNEL_PATH/include/linux/version.h |awk 'BEGIN { FS="\"" } { print $[]2 }'|tail -1`
+                 if test "x$linux_kvers" = "x"; then
+                   if test -f "$LINUX_KERNEL_PATH/include/linux/version-up.h"; then
+                     linux_kvers=`fgrep UTS_RELEASE $LINUX_KERNEL_PATH/include/linux/version-up.h |awk 'BEGIN { FS="\"" } { print $[]2 }'|tail -1`
+                     if test "x$linux_kvers" = "x"; then
+
+                       AC_MSG_ERROR(Linux headers lack version definition [2])
+                       exit 1
+                     else
+                       LINUX_VERSION="$linux_kvers"
+                      fi
+                    else
+                      AC_MSG_ERROR(Linux headers lack version definition)
+                     exit 1
+                   fi
+                 else
+                   LINUX_VERSION="$linux_kvers"
+                 fi
+                else
+                    enable_kernel_module="no"
+                 fi
+                if test ! -f "$LINUX_KERNEL_PATH/include/linux/autoconf.h"; then
+                    enable_kernel_module="no"
+                fi
+                if test "x$enable_kernel_module" = "xno"; then
+                 if test "x$with_linux_kernel_headers" != "x"; then
+                  AC_MSG_ERROR(No usable linux headers found at $LINUX_KERNEL_PATH)
+                  exit 1
+                 else
+                  AC_MSG_WARN(No usable linux headers found at $LINUX_KERNEL_PATH so disabling kernel module)
+                 fi
+                fi
+               fi
+               AC_MSG_RESULT(linux)
+               if test "x$enable_kernel_module" = "xyes"; then
+                ifdef([OPENAFS_CONFIGURE_LIBAFS],
+                  [LINUX_BUILD_VNODE_FROM_INODE(config,afs)],
+                  [LINUX_BUILD_VNODE_FROM_INODE(src/config,src/afs/LINUX)]
+                )
+                LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
+                LINUX_INODE_SETATTR_RETURN_TYPE
+                LINUX_NEED_RHCONFIG
+                LINUX_WHICH_MODULES
+                if test "x$ac_cv_linux_func_inode_setattr_returns_int" = "xyes" ; then
+                 AC_DEFINE(INODE_SETATTR_NOT_VOID)
+                fi
+                if test "x$ac_cv_linux_fs_struct_address_space_has_page_lock" = "xyes"; then 
+                 AC_DEFINE(STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK)
+                fi
+                :
+               fi
+                ;;
+        *-solaris*)
+               MKAFS_OSTYPE=SOLARIS
+                AC_MSG_RESULT(sun4)
+               SOLARIS_UFSVFS_HAS_DQRWLOCK
+                ;;
+        *-hpux*)
+               MKAFS_OSTYPE=HPUX
+                AC_MSG_RESULT(hp_ux)
+                ;;
+        *-irix*)
+               MKAFS_OSTYPE=IRIX
+                AC_MSG_RESULT(sgi)
+                ;;
+        *-aix*)
+               MKAFS_OSTYPE=AIX
+                AC_MSG_RESULT(rs_aix)
+                ;;
+        *-osf*)
+               MKAFS_OSTYPE=DUX
+                AC_MSG_RESULT(alpha_dux)
+               if test "x$enable_kernel_module" = "xyes"; then
+                if test "x$with_dux_kernel_headers" != "x"; then
+                  HEADER_RT=`ls ${with_dux_kernel_headers}/rt_preempt.h | head -1 | sed 's,/rt_preempt.h,,;s,/usr/sys/,,'`
+                else
+                  HEADER_RT=`ls /usr/sys/*/rt_preempt.h | head -1 | sed 's,/rt_preempt.h,,;s,/usr/sys/,,'`
+                fi
+               fi
+               if test "$HEADER_RT" = "*" ; then
+                       AC_MSG_ERROR([Need a configured kernel directory])
+               fi
+               AC_SUBST([HEADER_RT])
+                ;;
+        *-darwin*)
+               MKAFS_OSTYPE=DARWIN
+                AC_MSG_RESULT(ppc_darwin)
+                ;;
+       *-freebsd*)
+               MKAFS_OSTYPE=FBSD
+               AC_MSG_RESULT(i386_fbsd)
+               ;;
+       *-openbsd*)
+               MKAFS_OSTYPE=OBSD
+               AC_MSG_RESULT(i386_obsd)
+               ;;
+        *)
+                AC_MSG_RESULT($system)
+                ;;
+esac
+
+if test "x$with_afs_sysname" != "x"; then
+        AFS_SYSNAME="$with_afs_sysname"
+else
+       AC_MSG_CHECKING(your AFS sysname)
+       case $host in
+               i?86-*-freebsd4.2*)
+                       AFS_SYSNAME="i386_fbsd_42"
+                       ;;
+               hppa*-hp-hpux11*)
+                       AFS_SYSNAME="hp_ux110"
+                       ;;
+               hppa*-hp-hpux10*)
+                       AFS_SYSNAME="hp_ux102"
+                       ;;
+               powerpc-apple-darwin1.2*)
+                       AFS_SYSNAME="ppc_darwin_12"
+                       DARWIN_PLIST=src/libafs/afs.${AFS_SYSNAME}.plist
+                       DARWIN_INFOFILE=afs.${AFS_SYSNAME}.plist
+                       ;;
+               powerpc-apple-darwin1.3*)
+                       AFS_SYSNAME="ppc_darwin_13"
+                       DARWIN_PLIST=src/libafs/afs.${AFS_SYSNAME}.plist
+                       DARWIN_INFOFILE=afs.${AFS_SYSNAME}.plist
+                       ;;
+               powerpc-apple-darwin1.4*)
+                       AFS_SYSNAME="ppc_darwin_14"
+                       DARWIN_PLIST=src/libafs/afs.${AFS_SYSNAME}.plist
+                       DARWIN_INFOFILE=afs.${AFS_SYSNAME}.plist
+                       ;;
+               sparc-sun-solaris2.5*)
+                       AFS_SYSNAME="sun4x_55"
+                       ;;
+               sparc-sun-solaris2.6)
+                       AFS_SYSNAME="sun4x_56"
+                       ;;
+               sparc-sun-solaris2.7)
+                       AFS_SYSNAME="sun4x_57"
+                       ;;
+               sparc-sun-solaris2.8)
+                       AFS_SYSNAME="sun4x_58"
+                       ;;
+               sparc-sun-solaris2.9)
+                       AFS_SYSNAME="sun4x_59"
+                       ;;
+               alpha*-dec-osf4.0*)
+                       AFS_SYSNAME="alpha_dux40"
+                       ;;
+               alpha*-dec-osf5.0*)
+                       AFS_SYSNAME="alpha_dux50"
+                       ;;
+               mips-sgi-irix6.5)
+                       AFS_SYSNAME="sgi_65"
+                       ;;
+               ia64-*-linux*)
+                       AFS_SYSNAME="ia64_linuxXX"
+                       ;;
+               powerpc-*-linux*)
+                       AFS_SYSNAME="ppc_linuxXX"
+                       ;;
+               alpha*-linux*)
+                       AFS_SYSNAME="alpha_linux_XX"
+                       ;;
+               s390-*-linux*)
+                       AFS_SYSNAME="s390_linuxXX"
+                       ;;
+               sparc-*-linux*)
+                       AFS_SYSNAME="sparc_linuxXX"
+                       ;;
+               sparc64-*-linux*)
+                       AFS_SYSNAME="sparc64_linuxXX"
+                       ;;
+               i?86-*-linux*)
+                       AFS_SYSNAME="i386_linuxXX"
+                       ;;
+               parisc-*-linux-gnu)
+                       AFS_SYSNAME="parisc_linuxXX"
+                       ;;
+               power*-ibm-aix4.2*)
+                       AFS_SYSNAME="rs_aix42"
+                       ;;
+               power*-ibm-aix4.3*)
+                       AFS_SYSNAME="rs_aix42"
+                       ;;
+               *)
+                       AC_MSG_ERROR(An AFS sysname is required)
+                       exit 1
+                       ;;
+       esac
+       case $AFS_SYSNAME in
+               *_linux*)
+                       AFS_SYSKVERS=`echo $LINUX_VERSION | awk -F\. '{print $[]1 $[]2}'`
+                       if test "x${AFS_SYSKVERS}" = "x"; then
+                        AC_MSG_ERROR(Couldn't guess your Linux version. Please use the --with-afs-sysname option to configure an AFS sysname.)
+                       fi
+                       _AFS_SYSNAME=`echo $AFS_SYSNAME|sed s/XX\$/$AFS_SYSKVERS/`
+                       AFS_SYSNAME="$_AFS_SYSNAME"
+                       ;;
+       esac
+        AC_MSG_RESULT($AFS_SYSNAME)
+fi
+
+
+if test "x${MKAFS_OSTYPE}" = "xIRIX"; then
+        echo Skipping library tests because they confuse Irix.
+else
+  AC_CHECK_FUNCS(socket)
+
+  if test "$ac_cv_func_socket" = no; then
+    for lib in socket inet; do
+        if test "$HAVE_SOCKET" != 1; then
+                AC_CHECK_LIB(${lib}, socket,LIBS="$LIBS -l$lib";HAVE_SOCKET=1;AC_DEFINE(HAVE_SOCKET))
+        fi
+    done
+  fi
+  
+  AC_CHECK_FUNCS(connect)       
+
+  if test "$ac_cv_func_connect" = no; then
+    for lib in nsl; do
+        if test "$HAVE_CONNECT" != 1; then
+                AC_CHECK_LIB(${lib}, connect,LIBS="$LIBS -l$lib";HAVE_CONNECT=1;AC_DEFINE(HAVE_CONNECT))
+        fi
+    done
+  fi
+
+  AC_CHECK_FUNCS(gethostbyname)
+  if test "$ac_cv_func_gethostbyname" = no; then
+        for lib in dns nsl resolv; do
+          if test "$HAVE_GETHOSTBYNAME" != 1; then
+            AC_CHECK_LIB(${lib}, gethostbyname, LIBS="$LIBS -l$lib";HAVE_GETHOSTBYNAME=1;AC_DEFINE(HAVE_GETHOSTBYNAME))
+          fi
+        done    
+  fi    
+
+  AC_CHECK_FUNCS(res_search)
+  if test "$ac_cv_func_res_search" = no; then
+        for lib in dns nsl resolv; do
+          if test "$HAVE_RES_SEARCH" != 1; then
+            AC_CHECK_LIB(${lib}, res_search, LIBS="$LIBS -l$lib";HAVE_RES_SEARCH=1;AC_DEFINE(HAVE_RES_SEARCH))
+          fi
+        done    
+       if test "$HAVE_RES_SEARCH" = 1; then
+         LIB_res_search="-l$lib"       
+       fi
+  fi    
+fi
+
+PTHREAD_LIBS=error
+AC_CHECK_LIB(pthread, pthread_attr_init,
+             PTHREAD_LIBS="-lpthread")
+if test "x$PTHREAD_LIBS" = xerror; then
+        AC_CHECK_LIB(pthreads, pthread_attr_init,
+                PTHREAD_LIBS="-lpthreads")
+fi
+if test "x$PTHREAD_LIBS" = xerror; then
+        AC_CHECK_LIB(c_r, pthread_attr_init,
+                PTHREAD_LIBS="-lc_r")
+fi
+if test "x$PTHREAD_LIBS" = xerror; then
+        AC_CHECK_FUNC(pthread_attr_init, PTHREAD_LIBS="")
+fi
+if test "x$PTHREAD_LIBS" = xerror; then
+        AC_MSG_WARN(*** Unable to locate working posix thread library ***)
+fi
+AC_SUBST(PTHREAD_LIBS)
+
+WITH_OBSOLETE=NO
+if test "$enable_obsolete" = "yes"; then
+       WITH_OBSOLETE=YES
+fi
+
+WITH_INSECURE=NO
+if test "$enable_insecure" = "yes"; then
+       WITH_INSECURE=YES
+fi
+
+# Fast restart
+if test "$enable_fast_restart" = "yes"; then
+       AC_DEFINE(FAST_RESTART)
+fi
+
+if test "$enable_bitmap_later" = "yes"; then
+       AC_DEFINE(BITMAP_LATER)
+fi
+
+if test "$enable_full_vos_listvol_switch" = "yes"; then
+       AC_DEFINE(FULL_LISTVOL_SWITCH)
+fi
+
+if test "$enable_bos_restricted_mode" = "yes"; then
+       AC_DEFINE(BOS_RESTRICTED_MODE)
+fi
+
+if test "$enable_namei_fileserver" = "yes"; then
+       AC_DEFINE(AFS_NAMEI_ENV)
+fi
+
+if test "$enable_afsdb" = "yes"; then
+       LIB_AFSDB="$LIB_res_search"
+       AC_DEFINE(AFS_AFSDB_ENV)
+fi
+
+dnl check for tivoli
+AC_MSG_CHECKING(for tivoli tsm butc support)
+XBSA_CFLAGS=""
+if test "$enable_tivoli_tsm" = "yes"; then
+       XBSADIR1=/usr/tivoli/tsm/client/api/bin/xopen
+       XBSADIR2=/opt/tivoli/tsm/client/api/bin/xopen
+
+       if test -e "$XBSADIR1/xbsa.h"; then
+               XBSA_CFLAGS="-Dxbsa -I$XBSADIR1"
+               AC_MSG_RESULT([yes, $XBSA_CFLAGS])
+       elif test -e "$XBSADIR2/xbsa.h"; then
+               XBSA_CFLAGS="-Dxbsa -I$XBSADIR2"
+               AC_MSG_RESULT([yes, $XBSA_CFLAGS])
+       else
+               AC_MSG_RESULT([no, missing xbsa.h header file])
+       fi
+else
+       AC_MSG_RESULT([no])
+fi
+AC_SUBST(XBSA_CFLAGS)
+
+dnl checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(stdlib.h string.h unistd.h fcntl.h sys/time.h sys/file.h)
+AC_CHECK_HEADERS(netinet/in.h netdb.h sys/fcntl.h sys/mnttab.h sys/mntent.h)
+AC_CHECK_HEADERS(mntent.h sys/vfs.h sys/param.h sys/fs_types.h)
+AC_CHECK_HEADERS(sys/mount.h strings.h termios.h signal.h)
+AC_CHECK_HEADERS(windows.h malloc.h winsock2.h direct.h io.h)
+AC_CHECK_HEADERS(security/pam_modules.h siad.h usersec.h)
+
+AC_CHECK_FUNCS(utimes random srandom getdtablesize snprintf re_comp re_exec)
+
+dnl Directory PATH handling
+if test "x$enable_transarc_paths" = "xyes"  ; then 
+    afsconfdir=${afsconfdir=/usr/afs/etc}
+    viceetcdir=${viceetcdir=/usr/vice/etc}
+    afskerneldir=${afskerneldir=${viceetcdir}}
+    afssrvbindir=${afssrvbindir=/usr/afs/bin}
+    afssrvsbindir=${afssrvsbindir=/usr/afs/bin}
+    afssrvlibexecdir=${afssrvlibexecdir=/usr/afs/bin}
+    afsdbdir=${afsdbdir=/usr/afs/db}
+    afslogsdir=${afslogsdir=/usr/afs/logs}
+    afslocaldir=${afslocaldir=/usr/afs/local}
+    afsbackupdir=${afsbackupdir=/usr/afs/backup}
+    afsbosconfigdir=${afsbosconfigdir=/usr/afs/local}
+else 
+    afsconfdir=${afsconfdir='${sysconfdir}/openafs/server'}
+    viceetcdir=${viceetcdir='${sysconfdir}/openafs'}
+    afskerneldir=${afskerneldir='${libdir}/openafs'}
+    afssrvbindir=${afssrvbindir='${bindir}'}
+    afssrvsbindir=${afssrvsbindir='${sbindir}'}
+    afssrvlibexecdir=${afssrvlibexecdir='${libexecdir}/openafs'}
+    afsdbdir=${afsdbdir='${localstatedir}/openafs/db'}
+    afslogsdir=${afslogsdir='${localstatedir}/openafs/logs'}
+    afslocaldir=${afslocaldir='${localstatedir}/openafs'}
+    afsbackupdir=${afsbackupdir='${localstatedir}/openafs/backup'}
+    afsbosconfigdir=${afsbosconfigdir='${sysconfdir}/openafs'}
+fi
+AC_SUBST(afsconfdir)
+AC_SUBST(viceetcdir)
+AC_SUBST(afskerneldir)
+AC_SUBST(afssrvbindir)
+AC_SUBST(afssrvsbindir)
+AC_SUBST(afssrvlibexecdir)
+AC_SUBST(afsdbdir)
+AC_SUBST(afslogsdir)
+AC_SUBST(afslocaldir)
+AC_SUBST(afsbackupdir)
+AC_SUBST(afsbosconfigdir)
+
+if test "x$enable_kernel_module" = "xyes"; then
+ENABLE_KERNEL_MODULE=libafs
+fi
+
+AC_SUBST(AFS_SYSNAME)
+AC_SUBST(ENABLE_KERNEL_MODULE)
+AC_SUBST(LIB_AFSDB)
+AC_SUBST(LINUX_KERNEL_PATH)
+AC_SUBST(LINUX_VERSION)
+AC_SUBST(MKAFS_OSTYPE)
+AC_SUBST(TOP_SRCDIR)
+AC_SUBST(TOP_INCDIR)
+AC_SUBST(TOP_LIBDIR)
+AC_SUBST(DEST)
+AC_SUBST(WITH_OBSOLETE)
+AC_SUBST(WITH_INSECURE)
+AC_SUBST(DARWIN_INFOFILE)
+
+])
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..1da7f85
--- /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 = 1;
+               }
+               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
diff --git a/src/afs/LINUX/osi_vfs.hin b/src/afs/LINUX/osi_vfs.hin
new file mode 100644 (file)
index 0000000..ee0588b
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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
+ */
+
+/*
+ * Linux interpretations of vnode and vfs structs.
+ *
+ * The Linux "inode" has been abstracted to the fs independent part to avoid
+ * wasting 100+bytes per vnode.
+ */
+
+#ifndef OSI_VFS_H_
+#define OSI_VFS_H_
+
+/* The vnode should match the current implementation of the fs independent
+ * part of the Linux inode.
+ */
+/* The first cut is to continue to use a separate vnode pool. */
+/* LINUX VNODE INCLUDED BELOW -- DO NOT MODIFY */
+
+typedef struct vnode vnode_t;
+
+/* Map vnode fields to inode fields. */
+#define i_number       i_ino
+#define v_count                i_count
+#define v_op           i_op
+#if defined(AFS_LINUX24_ENV)
+#define v_fop           i_fop
+#endif
+#define v_type         i_mode
+#define v_vfsp         i_sb
+#define vfs_vnodecovered s_covered
+
+/* v_type bits map to mode bits: */
+#define VNON 0
+#define VREG S_IFREG
+#define VDIR S_IFDIR
+#define VBLK S_IFBLK
+#define VCHR S_IFCHR
+#define VLNK S_IFLNK
+#define VSOCK S_IFSOCK
+
+/* vcexcl - used only by afs_create */
+enum vcexcl { EXCL, NONEXCL } ;
+
+/* afs_open and afs_close needs to distinguish these cases */
+#define FWRITE O_WRONLY|O_RDWR|O_APPEND
+#define FTRUNC O_TRUNC
+
+
+#define IO_APPEND O_APPEND
+#define FSYNC O_SYNC
+
+#define VTOI(V)  ((struct inode*)V)
+#ifdef AFS_LINUX24_ENV
+#define VN_HOLD(V) atomic_inc(&((vnode_t*)V)->i_count)
+#else
+#define VN_HOLD(V) ((vnode_t*)V)->i_count++;
+#endif
+#define VN_RELE(V) osi_iput((struct inode *)V);
+#define VFS_STATFS(V, S) ((V)->s_op->statfs)((V), (S), sizeof(*(S)))
+
+
+
+/* Various mode bits */
+#define VWRITE S_IWUSR
+#define VREAD  S_IRUSR
+#define VEXEC  S_IXUSR
+#define VSUID  S_ISUID
+#define VSGID  S_ISGID
+
+
+#define vfs super_block
+
+typedef struct vattr {
+    int                va_type;        /* One of v_types above. */
+    size_t     va_size;
+    unsigned long va_blocks;
+    unsigned long va_blocksize;
+    int                va_mask;        /* AT_xxx operation to perform. */
+    umode_t    va_mode;        /* mode bits. */
+    uid_t      va_uid;
+    gid_t      va_gid;
+    int                va_fsid;        /* Not used? */
+    dev_t      va_rdev;
+    ino_t      va_nodeid;      /* Inode number */
+    nlink_t    va_nlink;       /* link count for file. */
+    struct timeval va_atime;
+    struct timeval va_mtime;
+    struct timeval va_ctime;
+} vattr_t;
+
+#define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
+
+
+/* va_masks - these should match their respective ATTR_xxx #defines in fs.h.
+ * afs_notify_change has to use the attr bits in both the Linux and AFS
+ * meanings. The glue layer code uses the ATTR_xxx style names.
+ */
+#define AT_SIZE                ATTR_SIZE
+#define AT_MODE                ATTR_MODE
+#define AT_UID         ATTR_UID
+#define AT_GID         ATTR_GID
+#define AT_MTIME       ATTR_MTIME
+
+
+#define vnodeops inode_operations
+
+#endif /* OSI_VFS_H_ */
diff --git a/src/afs/afs_dynroot.c b/src/afs/afs_dynroot.c
new file mode 100644 (file)
index 0000000..6e42e2b
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * 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
+ */
+
+/*
+ * Dynamic /afs volume support.
+ *
+ * Implements:
+ * afs_IsDynrootFid
+ * afs_GetDynrootFid
+ * afs_IsDynroot
+ * afs_RefreshDynroot
+ * afs_GetDynroot
+ * afs_PutDynroot
+ * afs_DynrootNewVnode
+ * afs_SetDynrootEnable
+ * afs_GetDynrootEnable
+ *
+ */
+
+#include <afsconfig.h>
+#include "../afs/param.h"
+
+#include "../afs/stds.h"
+#include "../afs/sysincludes.h" /* Standard vendor system headers */
+#include "../afs/afsincludes.h"
+#include "../afs/afs_osi.h"
+#include "../afsint/afsint.h"
+#include "../afs/lock.h"
+
+#include "../afs/prs_fs.h"
+#include "../afs/dir.h"
+
+#define AFS_DYNROOT_CELL       1
+#define AFS_DYNROOT_VOLUME     1
+#define AFS_DYNROOT_VNODE      1
+#define AFS_DYNROOT_UNIQUE     1
+
+#define VNUM2CIDX(vnum)                ((vnum) >> 2)
+#define VNUM2RW(vnum)          (((vnum) >> 1) & 1)
+#define CIDXRW2VNUM(cidx, rw)  (((cidx) << 2) | ((rw) << 1))
+
+static int afs_dynrootEnable = 0;
+
+static afs_rwlock_t afs_dynrootDirLock;
+/* Start of variables protected by afs_dynrootDirLock */
+static char *afs_dynrootDir = NULL;
+static int afs_dynrootDirLen;
+static int afs_dynrootDirLinkcnt;
+static int afs_dynrootCellCount;
+static int afs_dynrootVersion = 1;
+static int afs_dynrootVersionHigh = 1;
+/* End of variables protected by afs_dynrootDirLock */
+
+extern afs_int32 afs_cellindex;
+extern afs_rwlock_t afs_xvcache;
+
+/*
+ * Returns non-zero iff fid corresponds to the top of the dynroot volume.
+ */
+int
+afs_IsDynrootFid(struct VenusFid *fid)
+{
+    return
+       (afs_dynrootEnable &&
+        fid->Cell       == AFS_DYNROOT_CELL   &&
+        fid->Fid.Volume == AFS_DYNROOT_VOLUME &&
+        fid->Fid.Vnode  == AFS_DYNROOT_VNODE  &&
+        fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
+}
+
+/*
+ * Obtain the magic dynroot volume Fid.
+ */
+void
+afs_GetDynrootFid(struct VenusFid *fid) 
+{
+    fid->Cell       = AFS_DYNROOT_CELL;
+    fid->Fid.Volume = AFS_DYNROOT_VOLUME;
+    fid->Fid.Vnode  = AFS_DYNROOT_VNODE;
+    fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
+}
+
+/*
+ * Returns non-zero iff avc is a pointer to the dynroot /afs vnode.
+ */
+int
+afs_IsDynroot(avc)
+    struct vcache *avc;
+{
+    return afs_IsDynrootFid(&avc->fid);
+}
+
+/*
+ * Add directory entry by given name to a directory.  Assumes the
+ * caller has allocated the directory to be large enough to hold
+ * the necessary entry.
+ */
+static void
+afs_dynroot_addDirEnt(dirHeader, curPageP, curChunkP, name, vnode)
+    struct DirHeader *dirHeader;
+    int *curPageP;
+    int *curChunkP;
+    char *name;
+    int vnode;
+{
+    char *dirBase = (char *) dirHeader;
+    struct PageHeader *pageHeader;
+    struct DirEntry *dirEntry;
+    int sizeOfEntry, i, t1, t2;
+    int curPage = *curPageP;
+    int curChunk = *curChunkP;
+    int didNewPage = 0;
+
+    /*
+     * Check if we need to flip pages..  If so, init the new page.
+     */
+    sizeOfEntry = afs_dir_NameBlobs(name);
+    if (curChunk + sizeOfEntry > EPP) {
+       curPage++;
+       curChunk = 1;
+       didNewPage = 1;
+    }
+
+    pageHeader = (struct PageHeader *) (dirBase + curPage * AFS_PAGESIZE);
+    if (didNewPage) {
+       pageHeader->pgcount = 0;
+       pageHeader->tag = htons(1234);
+       pageHeader->freecount = 0;
+       pageHeader->freebitmap[0] = 0x01;
+       for (i = 1; i < EPP/8; i++)
+           pageHeader->freebitmap[i] = 0;
+
+       dirHeader->alloMap[curPage] = EPP - 1;
+    }
+
+    dirEntry = (struct DirEntry *) (pageHeader + curChunk);
+    dirEntry->flag        = 1;
+    dirEntry->length      = 0;
+    dirEntry->next        = 0;
+    dirEntry->fid.vnode   = htonl(vnode);
+    dirEntry->fid.vunique = htonl(1);
+    strcpy(dirEntry->name, name);
+
+    for (i = curChunk; i < curChunk + sizeOfEntry; i++) {
+       t1 = i / 8;
+       t2 = i % 8;
+       pageHeader->freebitmap[t1] |= (1 << t2);
+    }
+
+    /*
+     * Add the new entry to the correct hash chain.
+     */
+    i = DirHash(name);
+    dirEntry->next = dirHeader->hashTable[i];
+    dirHeader->hashTable[i] = htons(curPage * EPP + curChunk);
+
+    curChunk += sizeOfEntry;
+    dirHeader->alloMap[curPage] -= sizeOfEntry;
+
+    *curPageP = curPage;
+    *curChunkP = curChunk;
+}
+
+/*
+ * Regenerates the dynroot contents from the current list of
+ * cells.  Useful when the list of cells has changed due to
+ * an AFSDB lookup, for instance.
+ */
+void
+afs_RefreshDynroot()
+{
+    int cellidx, maxcellidx, i;
+    struct cell *c;
+    int curChunk, curPage;
+    int dirSize;
+    char *newDir, *dotCell;
+    struct DirHeader *dirHeader;
+    struct PageHeader *pageHeader;
+    struct DirEntry *dirEntry;
+    int doFlush = 0;
+    int linkCount = 0;
+
+    /*
+     * Save afs_cellindex here, in case it changes between the
+     * two loops.
+     */
+    maxcellidx = afs_cellindex;
+
+    /*
+     * Compute the amount of space we need for the fake dir
+     */
+    curChunk = 13;
+    curPage = 0;
+
+    for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
+       int sizeOfCurEntry;
+
+       c = afs_GetCellByIndex(cellidx, READ_LOCK);
+       if (!c) continue;
+
+       sizeOfCurEntry = afs_dir_NameBlobs(c->cellName);
+       if (curChunk + sizeOfCurEntry > EPP) {
+           curPage++;
+           curChunk = 1;
+       }
+       curChunk += sizeOfCurEntry;
+
+       dotCell = afs_osi_Alloc(strlen(c->cellName) + 2);
+       strcpy(dotCell, ".");
+       strcat(dotCell, c->cellName);
+       sizeOfCurEntry = afs_dir_NameBlobs(dotCell);
+       if (curChunk + sizeOfCurEntry > EPP) {
+           curPage++;
+           curChunk = 1;
+       }
+       curChunk += sizeOfCurEntry;
+
+       afs_PutCell(c, READ_LOCK);
+    }
+
+    dirSize = (curPage + 1) * AFS_PAGESIZE;
+    newDir = afs_osi_Alloc(dirSize);
+
+    /*
+     * Now actually construct the directory.
+     */
+    curChunk = 13;
+    curPage = 0;
+    dirHeader = (struct DirHeader *) newDir;
+
+    dirHeader->header.pgcount = 0;
+    dirHeader->header.tag = htons(1234);
+    dirHeader->header.freecount = 0;
+
+    dirHeader->header.freebitmap[0] = 0xff;
+    dirHeader->header.freebitmap[1] = 0x1f;
+    for (i = 2; i < EPP/8; i++)
+       dirHeader->header.freebitmap[i] = 0;
+    dirHeader->alloMap[0] = EPP - DHE - 1;
+    for (i = 1; i < MAXPAGES; i++)
+       dirHeader->alloMap[i] = EPP;
+    for (i = 0; i < NHASHENT; i++)
+       dirHeader->hashTable[i] = 0;
+
+    /* Install "." and ".." */
+    afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
+    afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
+    linkCount += 2;
+
+    for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
+       c = afs_GetCellByIndex(cellidx, READ_LOCK);
+       afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
+                             c->cellName, CIDXRW2VNUM(cellidx, 0));
+
+       dotCell = afs_osi_Alloc(strlen(c->cellName) + 2);
+       strcpy(dotCell, ".");
+       strcat(dotCell, c->cellName);
+       afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
+                             dotCell, CIDXRW2VNUM(cellidx, 1));
+
+       linkCount += 2;
+
+       afs_PutCell(c, READ_LOCK);
+    }
+
+    ObtainWriteLock(&afs_dynrootDirLock, 549);
+    if (afs_dynrootDir) afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
+    afs_dynrootDir = newDir;
+    afs_dynrootDirLen = dirSize;
+    afs_dynrootDirLinkcnt = linkCount;
+    if (afs_dynrootCellCount != maxcellidx) {
+       /*
+        * New cells added -- bump data version, invalidate vcache.
+        */
+       afs_dynrootCellCount = maxcellidx;
+       afs_dynrootVersion++;
+       afs_dynrootVersionHigh = osi_Time();
+       doFlush = 1;
+    }
+    ReleaseWriteLock(&afs_dynrootDirLock);
+
+    if (doFlush) {
+       afs_int32 retry;
+       struct vcache *tvc;
+       struct VenusFid tfid;
+
+       afs_GetDynrootFid(&tfid);
+       do {
+           retry = 0;
+           ObtainReadLock(&afs_xvcache);
+           tvc = afs_FindVCache(&tfid, 0, 0, &retry, 0);
+           ReleaseReadLock(&afs_xvcache);
+       } while (retry);
+       if (tvc) {
+           tvc->states &= ~(CStatd | CUnique);
+           osi_dnlc_purgedp(tvc);
+           afs_PutVCache(tvc);
+       }
+    }
+}
+
+/*
+ * Returns a pointer to the base of the dynroot directory in memory,
+ * length thereof, and a FetchStatus.
+ */
+void
+afs_GetDynroot(dynrootDir, dynrootLen, status)
+    char **dynrootDir;
+    int *dynrootLen;
+    struct AFSFetchStatus *status;
+{
+    ObtainReadLock(&afs_dynrootDirLock);
+    if (!afs_dynrootDir) {
+       ReleaseReadLock(&afs_dynrootDirLock);
+       afs_RefreshDynroot();
+       ObtainReadLock(&afs_dynrootDirLock);
+    }
+
+    if (dynrootDir) *dynrootDir = afs_dynrootDir;
+    if (dynrootLen) *dynrootLen = afs_dynrootDirLen;
+
+    if (status) {
+       memset(status, 0, sizeof(struct AFSFetchStatus));
+       status->FileType        = Directory;
+       status->LinkCount       = afs_dynrootDirLinkcnt;
+       status->Length          = afs_dynrootDirLen;
+       status->DataVersion     = afs_dynrootVersion;
+       status->CallerAccess    = PRSFS_LOOKUP | PRSFS_READ;
+       status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
+       status->UnixModeBits    = 0755;
+       status->ParentVnode     = 1;
+       status->ParentUnique    = 1;
+       status->dataVersionHigh = afs_dynrootVersionHigh;
+    }
+}
+
+/*
+ * Puts back the dynroot read lock.
+ */
+void
+afs_PutDynroot()
+{
+    ReleaseReadLock(&afs_dynrootDirLock);
+}
+
+/*
+ * Inform dynroot that a new vnode is being created.  Return value
+ * is non-zero if this vnode is handled by dynroot, in which case
+ * FetchStatus will be filled in.
+ */
+int
+afs_DynrootNewVnode(avc, status)
+    struct vcache *avc;
+    struct AFSFetchStatus *status;
+{
+    if (!afs_dynrootEnable) return 0;
+
+    if (afs_IsDynroot(avc)) {
+       afs_GetDynroot(0, 0, status);
+       afs_PutDynroot();
+       return 1;
+    }
+
+    /*
+     * Check if this is an entry under /afs, e.g. /afs/cellname.
+     */
+    if (avc->fid.Cell       == AFS_DYNROOT_CELL &&
+       avc->fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
+
+       struct cell *c;
+       int namelen, linklen, cellidx, rw;
+
+       cellidx = VNUM2CIDX(avc->fid.Fid.Vnode);
+       rw = VNUM2RW(avc->fid.Fid.Vnode);
+
+       c = afs_GetCellByIndex(cellidx, READ_LOCK);
+       if (!c) {
+           afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
+                    cellidx);
+           return 0;
+       }
+
+       memset(status, 0, sizeof(struct AFSFetchStatus));
+
+       if (c->states & CAlias) {
+           /*
+            * linkData needs to contain the name of the cell
+            * we're aliasing for.
+            */
+           struct cell *tca = c->alias;
+
+           if (!tca) {
+               afs_warn("dynroot: alias %s missing cell alias pointer\n",
+                        c->cellName);
+               linklen = 7;
+               avc->linkData = afs_osi_Alloc(linklen + 1);
+               strcpy(avc->linkData, "unknown");
+           } else {
+               int namelen = strlen(tca->cellName);
+               linklen = rw + namelen;
+               avc->linkData = afs_osi_Alloc(linklen + 1);
+               strcpy(avc->linkData, rw ? "." : "");
+               strcat(avc->linkData, tca->cellName);
+           }
+
+           status->UnixModeBits = 0755;
+       } else {
+           /*
+            * linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
+            */
+           namelen = strlen(c->cellName);
+           linklen = 1 + namelen + 10;
+           avc->linkData = afs_osi_Alloc(linklen + 1);
+           strcpy(avc->linkData, rw ? "%" : "#");
+           strcat(avc->linkData, c->cellName);
+           strcat(avc->linkData, ":root.cell");
+
+           status->UnixModeBits = 0644;
+       }
+
+       status->FileType        = SymbolicLink;
+       status->LinkCount       = 1;
+       status->Length          = linklen;
+       status->DataVersion     = 1;
+       status->CallerAccess    = PRSFS_LOOKUP | PRSFS_READ;
+       status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
+       status->ParentVnode     = 1;
+       status->ParentUnique    = 1;
+
+       afs_PutCell(c, READ_LOCK);
+       return 1;
+    }
+
+    return 0;
+}
+
+/*
+ * Enable or disable dynroot.  Returns 0 if successful.
+ */
+int
+afs_SetDynrootEnable(enable)
+    int enable;
+{
+    afs_dynrootEnable = enable;
+    return 0;
+}
+
+/*
+ * Check if dynroot support is enabled.
+ */
+int
+afs_GetDynrootEnable()
+{
+    return afs_dynrootEnable;
+}
diff --git a/src/afs/afs_nfsdisp.c b/src/afs/afs_nfsdisp.c
new file mode 100644 (file)
index 0000000..56c0549
--- /dev/null
@@ -0,0 +1,863 @@
+/*
+ * 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
+ */
+
+/*
+ * Implements:
+ */
+#include <afsconfig.h>
+#include "../afs/param.h"
+
+RCSID("$Header: /tmp/cvstemp/openafs/src/afs/afs_nfsdisp.c,v 1.1 2001/10/14 17:58:56 hartmans Exp $");
+
+#include "../afs/stds.h"
+#include "../afs/sysincludes.h" /* Standard vendor system headers */
+#if defined(AFS_SUN55_ENV) && !defined(AFS_NONFSTRANS) 
+#include "../rpc/types.h"
+#include "../rpc/auth.h"
+#include "../rpc/auth_unix.h"
+#include "../rpc/auth_des.h"
+#include "../rpc/auth_kerb.h"
+#include "../sys/tiuser.h"
+#include "../rpc/xdr.h"
+#include "../rpc/svc.h"
+#include "../nfs/nfs.h"
+#include "../nfs/export.h"
+#include "../nfs/nfs_clnt.h"
+#include "../nfs/nfs_acl.h"
+#include "../afs/afsincludes.h"        
+#include "../afs/afs_stats.h"   
+#include "../afs/exporter.h"
+
+static int xlatorinit_v2_done=0;
+static int xlatorinit_v3_done=0;
+
+extern int afs_nobody;
+extern int afs_NFSRootOnly;
+
+/* It's bigger than this, but we don't care about anything else */
+struct rfs_disp_tbl {
+       void  (*dis_proc)();    
+};
+
+struct afs_nfs_disp_tbl {
+    void (*afs_proc)();
+    void (*orig_proc)();
+};
+
+struct afs_nfs2_resp {
+    nfsstat status;
+};
+
+#ifndef ACL2_NPROC
+#define ACL2_NPROC     5
+#endif
+
+struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC];
+struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC];
+
+static int 
+is_afs_fh(fhandle_t *fhp) {
+    if ((fhp->fh_fsid.val[0] == AFS_VFSMAGIC) &&
+       (fhp->fh_fsid.val[1] == AFS_VFSFSID)) 
+       return 1;
+    return 0;
+}
+
+afs_int32 
+nfs2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp, fhandle_t **fh2pp)
+{
+    struct vnode *vp;
+    fhandle_t *fhp1=0;
+    fhandle_t *fhp2=0;
+    int errorcode;
+
+    *fh2pp = (fhandle_t *)0;
+    switch (which) {
+       case RFS_GETATTR:
+        case RFS_READLINK:
+        case RFS_STATFS:
+           fhp1 = (fhandle_t *)args;
+           break;
+       case RFS_SETATTR: 
+       {
+           struct nfssaargs *sargs = (struct nfssaargs *)args; 
+           fhp1 = (fhandle_t *)&sargs->saa_fh;
+           break;
+       } 
+        case RFS_LOOKUP: 
+       {
+           struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
+           fhp1 = (fhandle_t *)&sargs->da_fhandle;
+           break;
+       } 
+       case RFS_READ:
+       {
+           struct nfsreadargs *sargs = (struct nfsreadargs *)args;
+           fhp1 = (fhandle_t *)&sargs->ra_fhandle;
+           break;
+       } 
+        case RFS_WRITE: 
+       {
+           struct nfswriteargs *sargs = (struct nfswriteargs *)args;
+           fhp1 = (fhandle_t *)&sargs->wa_fhandle;
+           break;
+       } 
+        case RFS_CREATE: 
+       {
+           struct nfscreatargs *sargs = (struct nfscreatargs *)args;
+           fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
+           break;
+       } 
+        case RFS_REMOVE: 
+       {
+           struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
+           fhp1 = (fhandle_t *)&sargs->da_fhandle;
+           break;
+       }
+        case RFS_RENAME: 
+       {
+           struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
+           fhp1 = (fhandle_t *)&sargs->rna_from.da_fhandle;
+           fhp2 = (fhandle_t *)&sargs->rna_to.da_fhandle;
+           break;
+       } 
+        case RFS_LINK: 
+       {
+           struct nfslinkargs *sargs = (struct nfslinkargs *)args;
+           fhp1 = (fhandle_t *)&sargs->la_from;
+           fhp2 = (fhandle_t *)&sargs->la_to.da_fhandle;
+           break;
+       } 
+        case RFS_SYMLINK: 
+       {
+           struct nfsslargs *sargs = (struct nfsslargs *)args;
+           fhp1 = (fhandle_t *)&sargs->sla_from.da_fhandle;
+           break;
+       } 
+        case RFS_MKDIR: 
+       {
+           struct nfscreatargs *sargs = (struct nfscreatargs *)args;
+           fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
+           break;
+       } 
+        case RFS_RMDIR: 
+       {
+           struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
+           fhp1 = (fhandle_t *)&sargs->da_fhandle;
+           break;
+       } 
+        case RFS_READDIR: 
+       {
+           struct nfsrddirargs *sargs = (struct nfsrddirargs *)args;
+           fhp1 = (fhandle_t *)&sargs->rda_fh;
+           break;
+       } 
+       default:
+           return NULL;
+    }
+
+    /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
+    if (is_afs_fh(fhp1)) {
+       *fhpp = fhp1;
+       if (fhp2) 
+           *fh2pp = fhp2;
+       return 1;           
+    }
+    if (is_afs_fh(fhp2)) {
+       *fhpp = fhp1;
+       *fh2pp = fhp2;
+       return 1;           
+    }
+    return NULL;
+}
+
+afs_int32 
+acl2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp)
+{
+    fhandle_t *fhp;
+
+    switch(which) {
+    case ACLPROC2_NULL:
+    {
+       return NULL;
+    }
+    case ACLPROC2_GETACL: 
+    {
+       struct GETACL2args *sargs = (struct GETACL2args *) args;
+       fhp = &sargs->fh;
+       break;
+    }
+    case ACLPROC2_SETACL: 
+    {
+       struct SETACL2args *sargs = (struct SETACL2args *) args;
+       fhp = &sargs->fh;
+       break;
+    }
+    case ACLPROC2_GETATTR: 
+    {
+       struct GETATTR2args *sargs = (struct GETATTR2args *) args;
+       fhp = &sargs->fh;
+       break;
+    }
+    case ACLPROC2_ACCESS: 
+    {
+       struct ACCESS2args *sargs = (struct ACCESS2args *) args;
+       fhp = &sargs->fh;
+       break;
+    }
+    default:
+       return NULL;
+    }
+
+    if (is_afs_fh(fhp)) {
+       *fhpp = fhp;
+       return 1;
+    }
+
+    return NULL;
+}
+
+int
+afs_nfs2_dispatcher(int type, afs_int32 which, char *argp, 
+                   struct exportinfo **expp, 
+                   struct svc_req *rp, struct AFS_UCRED *crp)
+{
+    afs_int32 call = 0;
+    afs_int32 code = 0;
+    afs_int32 client = 0;
+    struct sockaddr *sa;
+    fhandle_t *fh = (fhandle_t *)argp;
+    fhandle_t *fh2 = (fhandle_t *)0;
+
+    if (!xlatorinit_v2_done)
+       return 2;
+
+    sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
+    client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+
+    AFS_GLOCK();
+    code = 0;
+    switch (type) {
+    case 0:
+       code = nfs2_to_afs_call(which, argp, &fh, &fh2);
+       break;
+    case 1:
+       code = acl2_to_afs_call(which, argp, &fh);
+       break;
+    default:
+       break;
+    }
+
+    if (code) {
+       struct afs_exporter *out = 0;
+       afs_int32 dummy;
+       static int once = 0;
+       struct SmallFid Sfid;
+
+       memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
+
+       /* We ran */
+       call = 1;
+       if (!once && *expp) {
+           afs_nobody = (*expp)->exi_export.ex_anon;
+           once = 1;
+       }
+       code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
+                                       client, &dummy, &out);
+       /* Be careful to release this */
+       if (!code && out)
+           EXP_RELE(out);
+
+       /* We ran and failed */
+       if (code == EINVAL) 
+           call = 2;
+    }
+
+    AFS_GUNLOCK();
+    return call;
+}
+
+void 
+afs_nfs2_smallfidder(struct nfsdiropres *dr)
+{
+    register fhandle_t *fhp = (fhandle_t *)&dr->dr_fhandle;
+    afs_int32 addr[2];
+    struct vcache *vcp;
+
+#if defined(AFS_SUN57_64BIT_ENV)
+    /* See also afs_fid() */    
+    memcpy((char *)addr, fhp->fh_data, 10);
+    addr[1] = (addr[1] >> 48) & 0xffff;
+#else 
+    memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
+#endif
+
+    AFS_GLOCK();
+    vcp = (struct vcache *)addr[0];
+
+    /* See also afs_osi_vget */
+    if (addr[1] == AFS_XLATOR_MAGIC)
+    {
+       if (dr->dr_status == NFS_OK) {
+           struct SmallFid Sfid;
+           struct cell *tcell;
+
+           /* Make up and copy out a SmallFid */
+           tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
+           Sfid.Volume = vcp->fid.Fid.Volume;
+           Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
+                                 (vcp->fid.Fid.Unique & 0xffffff));
+           afs_PutCell(tcell, READ_LOCK);
+           Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
+           fhp->fh_len = SIZEOF_SMALLFID;
+           memcpy(dr->dr_fhandle.fh_data, (char*)&Sfid, fhp->fh_len);
+       }
+
+       /* If we have a ref, release it */
+       if (vcp->vrefCount >= 1) 
+           AFS_RELE((struct vnode *) vcp);
+    } 
+    AFS_GUNLOCK();
+}
+
+void
+afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
+{
+    r->status = NFSERR_ACCES;
+}
+
+void afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
+{
+}
+
+void 
+afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
+{
+}
+
+void 
+afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
+{
+}
+
+#define NFS_V2_REQ(FUNCNAME, RFSOP, POST) \
+void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
+    u_int call; \
+    struct cred *svcred = curthread->t_cred; \
+    curthread->t_cred = (struct cred*)crp; \
+    call=afs_nfs2_dispatcher(0, RFSOP, (char *)args, &exp, rp, crp); \
+    if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
+    else { (*afs_rfs_disp_tbl[RFSOP].orig_proc)(args, xp, exp, rp, crp); \
+    if (POST && afs_NFSRootOnly && call) afs_nfs2_smallfidder(xp); } \
+    curthread->t_cred = svcred; \
+    return; \
+}
+
+NFS_V2_REQ(afs_nfs2_getattr, RFS_GETATTR, 0) 
+NFS_V2_REQ(afs_nfs2_setattr, RFS_SETATTR, 0)
+NFS_V2_REQ(afs_nfs2_lookup, RFS_LOOKUP, 1)
+NFS_V2_REQ(afs_nfs2_readlink, RFS_READLINK, 0);
+NFS_V2_REQ(afs_nfs2_read, RFS_READ, 0);
+NFS_V2_REQ(afs_nfs2_write, RFS_WRITE, 0);
+NFS_V2_REQ(afs_nfs2_create, RFS_CREATE, 1);
+NFS_V2_REQ(afs_nfs2_remove, RFS_REMOVE, 0);
+NFS_V2_REQ(afs_nfs2_rename, RFS_RENAME, 0);
+NFS_V2_REQ(afs_nfs2_link, RFS_LINK, 0);
+NFS_V2_REQ(afs_nfs2_symlink, RFS_SYMLINK, 0);
+NFS_V2_REQ(afs_nfs2_mkdir, RFS_MKDIR, 1);
+NFS_V2_REQ(afs_nfs2_rmdir, RFS_RMDIR, 0);
+NFS_V2_REQ(afs_nfs2_readdir, RFS_READDIR, 0);
+NFS_V2_REQ(afs_nfs2_statfs, RFS_STATFS, 0);
+
+struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
+    { afs_nfs2_null },
+    { afs_nfs2_getattr },
+    { afs_nfs2_setattr },
+    { afs_nfs2_root },
+    { afs_nfs2_lookup },
+    { afs_nfs2_readlink },
+    { afs_nfs2_read },
+    { afs_nfs2_writecache },   
+    { afs_nfs2_write },
+    { afs_nfs2_create },
+    { afs_nfs2_remove },       
+    { afs_nfs2_rename },
+    { afs_nfs2_link }, 
+    { afs_nfs2_symlink },
+    { afs_nfs2_mkdir },
+    { afs_nfs2_rmdir },
+    { afs_nfs2_readdir },
+    { afs_nfs2_statfs }
+};
+
+#define ACL_V2_REQ(FUNCNAME, ACLOP) \
+void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
+    u_int call; \
+    struct cred *svcred = curthread->t_cred; \
+    curthread->t_cred = (struct cred*)crp; \
+    call=afs_nfs2_dispatcher(1, ACLOP, (char *)args, &exp, rp, crp); \
+    if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
+    else (*afs_rfs_disp_tbl[ACLOP].orig_proc)(args, xp, exp, rp, crp); \
+    curthread->t_cred = svcred; \
+    return; \
+}
+
+ACL_V2_REQ(afs_acl2_getacl, ACLPROC2_GETACL)
+ACL_V2_REQ(afs_acl2_setacl, ACLPROC2_SETACL)
+ACL_V2_REQ(afs_acl2_getattr, ACLPROC2_GETATTR)
+ACL_V2_REQ(afs_acl2_access, ACLPROC2_ACCESS)
+
+struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC] = {
+    { afs_nfs2_null }, 
+    { afs_acl2_getacl }, 
+    { afs_acl2_setacl },
+    { afs_acl2_getattr }, 
+    { afs_acl2_access } 
+};
+
+/* Munge the dispatch tables to link us in first */
+void 
+afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl, 
+                 struct rfs_disp_tbl *_acl_tbl)
+{
+    int i;
+
+    if (xlatorinit_v2_done++) return;
+
+    for (i=0; i < RFS_NPROC; i++) {
+       afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
+       _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
+    }
+
+    for (i=0; i < ACL2_NPROC; i++) {
+       afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
+       _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
+    }
+}
+
+#ifndef RFS3_NPROC
+#define RFS3_NPROC     22
+#endif
+
+#ifndef ACL3_NPROC
+#define ACL3_NPROC     3
+#endif
+
+struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
+struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
+
+struct afs_nfs3_resp {
+    nfsstat3 status;
+    bool_t flags; 
+};
+
+static int 
+is_afs_fh3(nfs_fh3 *fhp) {
+    if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC) &&
+       (fhp->fh3_fsid.val[1] == AFS_VFSFSID)) 
+       return 1;
+    return 0;
+}
+
+void
+afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
+{
+    resp->status = NFS3ERR_ACCES;
+    resp->flags = FALSE;
+}
+
+afs_int32 
+nfs3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp, nfs_fh3 **fh2pp)
+{
+    struct vnode *vp;
+    nfs_fh3 *fhp1=0;
+    nfs_fh3 *fhp2=0;
+    int errorcode;
+
+    *fh2pp = (nfs_fh3 *)0;
+    switch (which) {
+        case NFSPROC3_GETATTR: 
+       {
+            GETATTR3args *arg = (GETATTR3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object;
+            break;
+        } 
+        case NFSPROC3_SETATTR: 
+       {
+            SETATTR3args *arg = (SETATTR3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object;
+            break;
+        } 
+        case NFSPROC3_LOOKUP: 
+       {
+            LOOKUP3args *arg = (LOOKUP3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->what.dir;
+            break;
+        } 
+        case NFSPROC3_ACCESS: 
+       {
+            ACCESS3args *arg = (ACCESS3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object;
+            break;
+        } 
+        case NFSPROC3_READLINK: 
+       {
+            READLINK3args *arg = (READLINK3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->symlink;       
+            break;
+        } 
+        case NFSPROC3_READ: 
+       {
+            READ3args *arg = (READ3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->file;
+            break;
+        } 
+        case NFSPROC3_WRITE: 
+       {
+            WRITE3args *arg = (WRITE3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->file;
+            break;
+        } 
+        case NFSPROC3_CREATE: 
+       {
+            CREATE3args *arg = (CREATE3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->where.dir;
+            break;
+        } 
+        case NFSPROC3_MKDIR: 
+       {
+            MKDIR3args *arg = (MKDIR3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->where.dir;
+            break;
+        } 
+        case NFSPROC3_SYMLINK: 
+       {
+            SYMLINK3args *arg = (SYMLINK3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->where.dir;
+            break;
+        } 
+        case NFSPROC3_MKNOD:
+       {
+            MKNOD3args *arg = (MKNOD3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->where.dir;
+            break;
+        } 
+        case NFSPROC3_REMOVE: 
+       {
+            REMOVE3args *arg = (REMOVE3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object.dir;
+            break;
+        } 
+        case NFSPROC3_RMDIR: 
+       {
+            RMDIR3args *arg = (RMDIR3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object.dir;
+            break;
+        } 
+        case NFSPROC3_RENAME: 
+       {
+            RENAME3args *arg = (RENAME3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->from.dir;
+            fhp2 = (nfs_fh3 *) &arg->to.dir;
+            break;
+        } 
+        case NFSPROC3_LINK: 
+       {
+            LINK3args *arg = (LINK3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->file;
+            fhp2 = (nfs_fh3 *) &arg->link.dir;
+            break;
+        } 
+        case NFSPROC3_READDIR: 
+       {
+            READDIR3args *arg = (READDIR3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->dir;
+            break;
+        } 
+        case NFSPROC3_READDIRPLUS: 
+       {
+            READDIRPLUS3args *arg = (READDIRPLUS3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->dir;
+            break;
+        } 
+        case NFSPROC3_FSSTAT: 
+       {
+            FSSTAT3args *arg = (FSSTAT3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->fsroot;
+            break;
+        } 
+        case NFSPROC3_FSINFO: 
+       {
+            FSINFO3args *arg = (FSINFO3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->fsroot;
+            break;
+        } 
+        case NFSPROC3_PATHCONF: 
+       {
+            PATHCONF3args *arg = (PATHCONF3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->object;
+            break;
+        } 
+        case NFSPROC3_COMMIT: 
+       {
+            COMMIT3args *arg = (COMMIT3args *)args;
+            fhp1 = (nfs_fh3 *) &arg->file;
+            break;
+        }
+       default:
+           return NULL;
+    }
+
+    /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
+    if (is_afs_fh3(fhp1)) {
+       *fhpp = fhp1;
+       if (fhp2) 
+           *fh2pp = fhp2;
+       return 1;           
+    }
+    if (is_afs_fh3(fhp2)) {
+       *fhpp = fhp1;
+       *fh2pp = fhp2;
+       return 1;           
+    }
+    return NULL;
+}
+
+afs_int32 
+acl2_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp)
+{
+    nfs_fh3 *fhp;
+
+    switch(which) {
+    case ACLPROC3_GETACL: 
+    {
+        struct GETACL3args *sargs = (struct GETACL3args *) args;
+        fhp = &sargs->fh;
+        break;
+    }
+    case ACLPROC3_SETACL: 
+    {
+        struct SETACL3args *sargs = (struct SETACL3args *) args;
+        fhp = &sargs->fh;
+        break;
+    }
+    default:
+       return NULL;
+    }
+
+    if (is_afs_fh3(fhp)) {
+       *fhpp = fhp;
+       return 1;
+    }
+
+    return NULL;
+}
+
+int
+afs_nfs3_dispatcher(int type, afs_int32 which, char *argp, 
+                   struct exportinfo **expp, 
+                   struct svc_req *rp, struct AFS_UCRED *crp)
+{
+    afs_int32 call = 0;
+    afs_int32 code = 0;
+    afs_int32 client = 0;
+    struct sockaddr *sa;
+    nfs_fh3 *fh = (nfs_fh3 *)argp;
+    nfs_fh3 *fh2 = (nfs_fh3 *)0;
+
+    if (!xlatorinit_v3_done)
+       return 2;
+
+    sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
+    client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+
+    AFS_GLOCK();
+    code = 0;
+    switch (type) {
+    case 0:
+       code = nfs3_to_afs_call(which, argp, &fh, &fh2);
+       break;
+    case 1:
+       code = acl3_to_afs_call(which, argp, &fh);
+       break;
+    default:
+       break;
+    }
+
+    if (code) {
+       struct afs_exporter *out = 0;
+       afs_int32 dummy;
+       static int once = 0;
+       struct SmallFid Sfid;
+
+       memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
+
+       /* We ran */
+       call = 1;
+       if (!once && *expp) {
+           afs_nobody = (*expp)->exi_export.ex_anon;
+           once = 1;
+       }
+       code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
+                                       client, &dummy, &out);
+       /* Be careful to release this */
+       if (!code && out)
+           EXP_RELE(out);
+
+       /* We ran and failed */
+       if (code == EINVAL) 
+           call = 2;
+    }
+
+    AFS_GUNLOCK();
+    return call;
+}
+
+void 
+afs_nfs3_smallfidder(struct nfs_fh3 *fhp int status)
+{
+    afs_int32 addr[2];
+    struct vcache *vcp;
+
+#if defined(AFS_SUN57_64BIT_ENV)
+    /* See also afs_fid() */    
+    memcpy((char *)addr, fhp->fh3_data, 10);
+    addr[1] = (addr[1] >> 48) & 0xffff;
+#else 
+    memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
+#endif
+
+    AFS_GLOCK();
+    vcp = (struct vcache *)addr[0];
+
+    /* See also afs_osi_vget */
+    if (addr[1] == AFS_XLATOR_MAGIC)
+    {
+       if (status == NFS_OK) {
+           struct SmallFid Sfid;
+           struct cell *tcell;
+
+           /* Make up and copy out a SmallFid */
+           tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
+           Sfid.Volume = vcp->fid.Fid.Volume;
+           Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
+                                 (vcp->fid.Fid.Unique & 0xffffff));
+           afs_PutCell(tcell, READ_LOCK);
+           Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
+           fhp->fh3_len = SIZEOF_SMALLFID;
+           memcpy(fhp->fh3_data, (char*)&Sfid, fhp->fh3_len);
+       }
+
+       /* If we have a ref, release it */
+       if (vcp->vrefCount >= 1) 
+           AFS_RELE((struct vnode *) vcp);
+    } 
+    AFS_GUNLOCK();
+}
+
+#define NFS_V3_REQ(FUNCNAME, NFSOP, POST, RESP, RESPP) \
+void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
+    u_int call; \
+    struct cred *svcred = curthread->t_cred; \
+    curthread->t_cred = (struct cred*)crp; \
+    call=afs_nfs3_dispatcher(0, NFSOP, (char *)args, &exp, rp, crp); \
+    if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
+    else { (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
+    if (POST && afs_NFSRootOnly && call) { \
+    RESP *resp = ( RESP *)xp; \
+    afs_nfs3_smallfidder( RESPP , resp->status); } \
+    curthread->t_cred = svcred; \
+    return; \
+}
+
+NFS_V3_REQ(afs_nfs3_getattr, NFSPROC3_GETATTR, 0, x, x) 
+NFS_V3_REQ(afs_nfs3_setattr, NFSPROC3_SETATTR, 0, x, x)
+NFS_V3_REQ(afs_nfs3_lookup, NFSPROC3_LOOKUP, 1, LOOKUP3res, &resp->resok.object)
+NFS_V3_REQ(afs_nfs3_access, NFSPROC3_ACCESS, 0, x, x);
+NFS_V3_REQ(afs_nfs3_readlink, NFSPROC3_READLINK, 0, x, x);
+NFS_V3_REQ(afs_nfs3_read, NFSPROC3_READ, 0, x, x);
+NFS_V3_REQ(afs_nfs3_write, NFSPROC3_WRITE, 0, x, x);
+NFS_V3_REQ(afs_nfs3_create, NFSPROC3_CREATE, 1, CREATE3res, &resp->resok.obj.handle);
+NFS_V3_REQ(afs_nfs3_mkdir, NFSPROC3_MKDIR, 1, MKDIR3res, &resp->resok.obj.handle);
+NFS_V3_REQ(afs_nfs3_symlink, NFSPROC3_SYMLINK, 0, x, x);
+NFS_V3_REQ(afs_nfs3_mknod, NFSPROC3_MKNOD, 0, x, x);
+NFS_V3_REQ(afs_nfs3_remove, NFSPROC3_REMOVE, 0, x, x);
+NFS_V3_REQ(afs_nfs3_rmdir, NFSPROC3_RMDIR, 0, x, x);
+NFS_V3_REQ(afs_nfs3_rename, NFSPROC3_RENAME, 0, x, x);
+NFS_V3_REQ(afs_nfs3_link, NFSPROC3_LINK, 0, x, x);
+NFS_V3_REQ(afs_nfs3_readdir, NFSPROC3_READDIR, 0, x, x);
+NFS_V3_REQ(afs_nfs3_readdirplus, NFSPROC3_READDIRPLUS, 0, x, x);
+NFS_V3_REQ(afs_nfs3_fsstat, NFSPROC3_FSSTAT, 0, x, x);
+NFS_V3_REQ(afs_nfs3_fsinfo, NFSPROC3_FSINFO, 0, x, x);
+NFS_V3_REQ(afs_nfs3_pathconf, NFSPROC3_PATHCONF, 0, x, x);
+NFS_V3_REQ(afs_nfs3_commit, NFSPROC3_COMMIT, 0, x, x);
+
+struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS_NPROC] = {
+    { afs_nfs2_null },
+    { afs_nfs3_getattr },
+    { afs_nfs3_setattr },
+    { afs_nfs3_lookup },
+    { afs_nfs3_access },
+    { afs_nfs3_readlink },
+    { afs_nfs3_read },
+    { afs_nfs3_write },
+    { afs_nfs3_create },
+    { afs_nfs3_mkdir },
+    { afs_nfs3_symlink },
+    { afs_nfs3_mknod },
+    { afs_nfs3_remove },        
+    { afs_nfs3_rmdir },
+    { afs_nfs3_rename },
+    { afs_nfs3_link },  
+    { afs_nfs3_readdir },
+    { afs_nfs3_readdirplus },
+    { afs_nfs3_fsstat },
+    { afs_nfs3_fsinfo },
+    { afs_nfs3_pathconf },
+    { afs_nfs3_commit }
+};
+
+#define ACL_V3_REQ(FUNCNAME, NFSOP) \
+void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
+    u_int call; \
+    struct cred *svcred = curthread->t_cred; \
+    curthread->t_cred = (struct cred*)crp; \
+    call=afs_nfs3_dispatcher(1, NFSOP, (char *)args, &exp, rp, crp); \
+    if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
+    else (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
+    curthread->t_cred = svcred; \
+    return; \
+}
+
+ACL_V3_REQ(afs_acl3_getacl, ACLPROC3_GETACL)
+ACL_V3_REQ(afs_acl3_setacl, ACLPROC3_SETACL)
+
+struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC] = {
+    { afs_nfs2_null }, 
+    { afs_acl3_getacl }, 
+    { afs_acl3_setacl },
+};
+
+/* Munge the dispatch tables to link us in first */
+void 
+afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl, 
+                  struct rfs_disp_tbl *_acl_tbl)
+{
+    int i;
+
+    if (xlatorinit_v3_done++) return;
+
+    for (i=0; i < RFS3_NPROC; i++) {
+        afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
+        _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
+    }
+
+    for (i=0; i < ACL3_NPROC; i++) {
+        afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
+        _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
+    }
+}
+#endif /* !defined(AFS_NONFSTRANS)