From 25c66964380a609ff894d6217deb97c1fa33b446 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Sun, 14 Oct 2001 17:58:46 +0000 Subject: [PATCH] Initial revision --- acinclude.m4 | 482 ++++++++++++++++++ src/WINNT/afsd/cm_dns.c | 687 +++++++++++++++++++++++++ src/WINNT/afsd/cm_dns.h | 27 + src/WINNT/afsd/cm_dns_private.h | 217 ++++++++ src/WINNT/afsd/cm_freelance.c | 525 +++++++++++++++++++ src/WINNT/afsd/cm_freelance.h | 19 + src/afs/LINUX/osi_vfs.hin | 114 +++++ src/afs/afs_dynroot.c | 461 +++++++++++++++++ src/afs/afs_nfsdisp.c | 863 ++++++++++++++++++++++++++++++++ 9 files changed, 3395 insertions(+) create mode 100644 acinclude.m4 create mode 100644 src/WINNT/afsd/cm_dns.c create mode 100644 src/WINNT/afsd/cm_dns.h create mode 100644 src/WINNT/afsd/cm_dns_private.h create mode 100644 src/WINNT/afsd/cm_freelance.c create mode 100644 src/WINNT/afsd/cm_freelance.h create mode 100644 src/afs/LINUX/osi_vfs.hin create mode 100644 src/afs/afs_dynroot.c create mode 100644 src/afs/afs_nfsdisp.c diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 000000000..505148178 --- /dev/null +++ b/acinclude.m4 @@ -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 index 000000000..b0e1da0e2 --- /dev/null +++ b/src/WINNT/afsd/cm_dns.c @@ -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 +#include +#ifndef DJGPP +#include +#include +#endif +#include "cm_dns_private.h" +#include "cm_dns.h" +#include +#include + +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= '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; irr_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; irr_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 index 000000000..1e5d28c8a --- /dev/null +++ b/src/WINNT/afsd/cm_dns.h @@ -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 index 000000000..1344fe0dc --- /dev/null +++ b/src/WINNT/afsd/cm_dns_private.h @@ -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 +#include +#include +#include +/*#else + #include */ +#endif + +#ifdef KERNEL +#define SOCKET struct osi_socket * +#else +#define SOCKET int +#endif + +#define SOCKADDR_IN struct sockaddr_in + +#include +#include + + +#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 */ + 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 index 000000000..1da7f857d --- /dev/null +++ b/src/WINNT/afsd/cm_freelance.c @@ -0,0 +1,525 @@ +#include +#include + +#ifndef DJGPP +#include +#include +#else +#include +#endif /* !DJGPP */ +#include +#include +#include + +#include + +#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; inamep, 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; icell = 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; inextp) { + 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; inamep=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; ii_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 index 000000000..6e42e2b23 --- /dev/null +++ b/src/afs/afs_dynroot.c @@ -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 +#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 index 000000000..56c0549df --- /dev/null +++ b/src/afs/afs_nfsdisp.c @@ -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 +#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) -- 2.39.5