--- /dev/null
+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)
+
+])
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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);
+
+
+
--- /dev/null
+/* 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_
+
--- /dev/null
+#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 */
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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)