Use WebNFS to obtain file handles for mount(2).
authorRainer Orth <ro@techfak.uni-bielefeld.de>
Thu, 9 Oct 2003 20:33:44 +0000 (20:33 +0000)
committerRainer Orth <ro@techfak.uni-bielefeld.de>
Thu, 9 Oct 2003 20:33:44 +0000 (20:33 +0000)
* NEWS: Document WebNFS support.

* configure.in: Check for public mount option.
* include/am_compat.h (MNTTAB_OPT_PUBLIC): Define if missing.
* doc/am-utils.texi (opts Option): Renamed webnfs to public,
update description.

* amd/amd.h (FSF_WEBNFS): New mntfs flag.
* include/am_utils.h (RPC_XID_WEBNFS): New XID type.

* amd/amfs_host.c (amfs_host_mount, amfs_host_umounted): Reject
WebNFS mount/umount attempts.
* amd/ops_nfs.c (got_nfs_fh_mount): Renamed from got_nfs_fh.
(got_nfs_fh_webnfs): New function.
(flush_nfs_fhandle_cache): Don't invalidate port for WebNFS servers.
(prime_nfs_fhandle_cache): Likewise.
Remove unconditional return of public file handle for WebNFS, but
get NFS file handles via mountd or WebNFS instead.
(webnfs_lookup): New function.
(nfs_umounted): Don't inform mountd if MFF_WEBNFS.
* amd/rpc_fwd.c (fwd_packet, fwd_reply): Send/receive WebNFS
packets.
* amd/srvr_nfs.c (recompute_portmap): Don't contact portmap for
WebNFS servers.
Mention host in info message.
(find_nfs_srvr): Handle public mount option.
Prefer NFSv3/tcp if the client supports it.
Allow port mount option to override default or result from portmap
lookup.

* libamu/xdr_func.c (xdr_diropargs3, xdr_filename3,
xdr_LOOKUP3args, xdr_LOOKUP3res, xdr_LOOKUP3resfail,
xdr_LOOKUP3resok, xdr_nfs_fh3, xdr_nfsstat3): New functions.
* include/am_xdr_func.h: Declare them.
* configure.in: Check for them.
* conf/nfs_prot/nfs_prot_linux.h: Provide missing NFSv3
definitions and types.

14 files changed:
ChangeLog
NEWS
amd/amd.h
amd/amfs_host.c
amd/ops_nfs.c
amd/rpc_fwd.c
amd/srvr_nfs.c
conf/nfs_prot/nfs_prot_linux.h
configure.in
doc/am-utils.texi
include/am_compat.h
include/am_utils.h
include/am_xdr_func.h
libamu/xdr_func.c

index efb13fb42ce5154cc461222aa051a18a20bd099f..cb8fb59318b642299553d4c42fd588269fa5108a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       Use WebNFS to obtain file handles for mount(2).
+
+       * NEWS: Document WebNFS support.
+
+       * configure.in: Check for public mount option.
+       * include/am_compat.h (MNTTAB_OPT_PUBLIC): Define if missing.
+       * doc/am-utils.texi (opts Option): Renamed webnfs to public,
+       update description.
+
+       * amd/amd.h (FSF_WEBNFS): New mntfs flag.
+       * include/am_utils.h (RPC_XID_WEBNFS): New XID type.
+       
+       * amd/amfs_host.c (amfs_host_mount, amfs_host_umounted): Reject
+       WebNFS mount/umount attempts.
+       * amd/ops_nfs.c (got_nfs_fh_mount): Renamed from got_nfs_fh.
+       (got_nfs_fh_webnfs): New function.
+       (flush_nfs_fhandle_cache): Don't invalidate port for WebNFS servers.
+       (prime_nfs_fhandle_cache): Likewise.
+       Remove unconditional return of public file handle for WebNFS, but
+       get NFS file handles via mountd or WebNFS instead.
+       (webnfs_lookup): New function.
+       (nfs_umounted): Don't inform mountd if MFF_WEBNFS.
+       * amd/rpc_fwd.c (fwd_packet, fwd_reply): Send/receive WebNFS
+       packets.
+       * amd/srvr_nfs.c (recompute_portmap): Don't contact portmap for
+       WebNFS servers.
+       Mention host in info message.
+       (find_nfs_srvr): Handle public mount option.
+       Prefer NFSv3/tcp if the client supports it.
+       Allow port mount option to override default or result from portmap
+       lookup.
+       
+       * libamu/xdr_func.c (xdr_diropargs3, xdr_filename3,
+       xdr_LOOKUP3args, xdr_LOOKUP3res, xdr_LOOKUP3resfail,
+       xdr_LOOKUP3resok, xdr_nfs_fh3, xdr_nfsstat3): New functions.
+       * include/am_xdr_func.h: Declare them.
+       * configure.in: Check for them.
+       * conf/nfs_prot/nfs_prot_linux.h: Provide missing NFSv3
+       definitions and types.
+
 2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        Support IRIX 6 private mount option.
diff --git a/NEWS b/NEWS
index dce6ed0a11fb4380e3afb4b33a9be71746af421e..cb681351117252597e0c6ffb0132797cb0cedd74 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@
        sparc-sun-solaris2.10
        x86_64-unknown-linux-rh2.9.5AS
 
+- fully support WebNFS as per RFC 2054.  It now tries v3/TCP first, falling
+  back to v2/UDP if this doesn't work.  The "webnfs" pseudo-mount options
+  has been renamed (again) to "public" to match Solaris 2.
+
 - bugs fixed:
        * fixed nfsx support
        * fixed a race involving late replies to mountd, etc queries
index 498b86bee4eae5b96808f53f53dee91ef8cb0bd8..600e445a3929ac7c25ff13bb47c7784fc18ab1dc 100644 (file)
--- a/amd/amd.h
+++ b/amd/amd.h
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amd.h,v 1.47 2003/10/09 05:13:58 ib42 Exp $
+ * $Id: amd.h,v 1.48 2003/10/09 20:33:45 ro Exp $
  *
  */
 
 #define        FSF_ERROR       0x0004  /* Permanent error has occurred */
 #define        FSF_WANT        0x0008  /* Want a wakeup call */
 #define        FSF_PINGING     0x0010  /* Already doing pings */
+#define        FSF_WEBNFS      0x0020  /* Don't try to contact portmapper */
 #define        FSRV_ERROR(fs)  ((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR))
 #define        FSRV_ISDOWN(fs) ((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID)))
 #define        FSRV_ISUP(fs)   (!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID)))
index 010f93cda2df8c2ad9eb5db4a0bfe3920579457e..2969736dcf6be2a4397981eddc3d6cbf49460923 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amfs_host.c,v 1.24 2003/10/02 16:29:28 ro Exp $
+ * $Id: amfs_host.c,v 1.25 2003/10/09 20:33:45 ro Exp $
  *
  */
 
@@ -316,6 +316,14 @@ amfs_host_mount(am_node *am, mntfs *mf)
   struct timeval tv;
   u_long mnt_version;
 
+  /*
+   * WebNFS servers don't necessarily run mountd.
+   */
+  if (mf->mf_flags & MFF_WEBNFS) {
+    plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
+    return EIO;
+  }
+
   /*
    * Read the mount list
    */
@@ -619,6 +627,14 @@ amfs_host_umounted(mntfs *mf)
   if (mf->mf_error || mf->mf_refc > 1 || !mf->mf_server)
     return;
 
+  /*
+   * WebNFS servers shouldn't ever get here.
+   */
+  if (mf->mf_flags & MFF_WEBNFS) {
+    plog(XLOG_ERROR, "amfs_host_umounted: cannot support WebNFS");
+    return;
+  }
+
   /*
    * Take a copy of the server hostname, address, and NFS version
    * to mount version conversion.
index 652bfe77f12f6bcdb8c14dced58dc0b93a7c8eab..1bd0941f1b233501438d48b87a1fbe2b1b496ca2 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_nfs.c,v 1.33 2003/10/02 16:29:28 ro Exp $
+ * $Id: ops_nfs.c,v 1.34 2003/10/09 20:33:45 ro Exp $
  *
  */
 
@@ -110,6 +110,7 @@ static int nfs_mount(am_node *am, mntfs *mf);
 static int nfs_umount(am_node *am, mntfs *mf);
 static void nfs_umounted(mntfs *mf);
 static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan);
+static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan);
 static int fh_id = 0;
 
 /* globals */
@@ -170,10 +171,10 @@ find_nfs_fhandle_cache(opaque_t arg, int done)
 
 
 /*
- * Called when a filehandle appears
+ * Called when a filehandle appears via the mount protocol
  */
 static void
-got_nfs_fh(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
+got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
 {
   fh_cache *fp;
   struct fhstatus res;
@@ -233,6 +234,70 @@ got_nfs_fh(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, o
 }
 
 
+/*
+ * Called when a filehandle appears via WebNFS
+ */
+static void
+got_nfs_fh_webnfs(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
+{
+  fh_cache *fp;
+  nfsdiropres res;
+#ifdef HAVE_FS_NFS3
+  LOOKUP3res res3;
+#endif /* HAVE_FS_NFS3 */
+
+  fp = find_nfs_fhandle_cache(arg, done);
+  if (!fp)
+    return;
+
+  /*
+   * retrieve the correct RPC reply for the file handle, based on the
+   * NFS protocol version.
+   */
+#ifdef HAVE_FS_NFS3
+  if (fp->fh_nfs_version == NFS_VERSION3) {
+    memset(&res3, 0, sizeof(res3));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
+                                   (XDRPROC_T_TYPE) xdr_LOOKUP3res);
+    fp->fh_status = unx_error(res3.status);
+    memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
+    fp->fh_nfs_handle.v3.fh3_length = res3.res_u.ok.object.fh3_length;
+    memmove(fp->fh_nfs_handle.v3.fh3_u.data,
+           res3.res_u.ok.object.fh3_u.data,
+           fp->fh_nfs_handle.v3.fh3_length);
+  } else {
+#endif /* HAVE_FS_NFS3 */
+    memset(&res, 0, sizeof(res));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
+                                   (XDRPROC_T_TYPE) xdr_diropres);
+    fp->fh_status = unx_error(res.dr_status);
+    memmove(&fp->fh_nfs_handle.v2, &res.dr_u.dr_drok_u.drok_fhandle, NFS_FHSIZE);
+#ifdef HAVE_FS_NFS3
+  }
+#endif /* HAVE_FS_NFS3 */
+
+  if (!fp->fh_error) {
+    dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+  } else {
+    plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+    /*
+     * Force the error to be EACCES. It's debatable whether it should be
+     * ENOENT instead, but the server really doesn't give us any clues, and
+     * EACCES is more in line with the "filehandle denied" message.
+     */
+    fp->fh_error = EACCES;
+  }
+
+  /*
+   * Wakeup anything sleeping on this filehandle
+   */
+  if (fp->fh_wchan) {
+    dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
+    wakeup(fp->fh_wchan);
+  }
+}
+
+
 void
 flush_nfs_fhandle_cache(fserver *fs)
 {
@@ -240,7 +305,11 @@ flush_nfs_fhandle_cache(fserver *fs)
 
   ITER(fp, fh_cache, &fh_head) {
     if (fp->fh_fs == fs || fs == 0) {
-      fp->fh_sin.sin_port = (u_short) 0;
+      /*
+       * Only invalidate port info for non-WebNFS servers
+       */
+      if (!(fp->fh_fs->fs_flags & FSF_WEBNFS))
+       fp->fh_sin.sin_port = (u_short) 0;
       fp->fh_error = -1;
     }
   }
@@ -385,36 +454,25 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *
   }
 
   /*
-   * If the address has changed then don't try to re-use the
-   * port information
+   * Either fp has been freshly allocated or the address has changed.
+   * Initialize address and nfs version.  Don't try to re-use the port
+   * information unless using WebNFS where the port is fixed either by
+   * the spec or the "port" mount option.
    */
   if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
     fp->fh_sin = *fs->fs_ip;
-    fp->fh_sin.sin_port = 0;
+    if (!(mf->mf_flags & MFF_WEBNFS))
+       fp->fh_sin.sin_port = 0;
     fp->fh_nfs_version = fs->fs_version;
   }
+
   fp->fh_fs = dup_srvr(fs);
   fp->fh_path = strdup(path);
 
-  if (mf->mf_flags & MFF_WEBNFS) {
-    dlog("Using public filehandle for '%s'", mf->mf_info);
-    memset(&fp->fh_nfs_handle, 0, sizeof(fp->fh_nfs_handle));
-    if (fhbuf) {
-#ifdef HAVE_FS_NFS3
-      if (fp->fh_nfs_version == NFS_VERSION3)
-       memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
-               sizeof(fp->fh_nfs_handle.v3));
-      else
-#endif /* HAVE_FS_NFS3 */
-       memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2),
-               sizeof(fp->fh_nfs_handle.v2));
-    }
-    wakeup(get_mntfs_wchan(mf));
-    fp->fh_error = 0;
-    return 0;
-  }
-
-  error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, get_mntfs_wchan(mf));
+  if (mf->mf_flags & MFF_WEBNFS)
+    error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
+  else
+    error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh_mount, get_mntfs_wchan(mf));
   if (error) {
     /*
      * Local error - cache for a short period
@@ -531,6 +589,91 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
 }
 
 
+static int
+webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan)
+{
+  struct rpc_msg wnfs_msg;
+  int len;
+  char iobuf[UDPMSGSIZE];
+  int error;
+  u_long proc;
+  XDRPROC_T_TYPE xdr_fn;
+  voidp argp;
+  nfsdiropargs args;
+#ifdef HAVE_FS_NFS3
+  LOOKUP3args args3;
+#endif
+  char *wnfs_path;
+
+  if (!nfs_auth) {
+    error = make_nfs_auth();
+    if (error)
+      return error;
+  }
+
+  if (fp->fh_sin.sin_port == 0) {
+    /* FIXME: wrong, don't discard sin_port in the first place for WebNFS. */
+    plog(XLOG_WARNING, "webnfs_lookup: port == 0 for nfs on %s, fixed",
+        fp->fh_fs->fs_host);
+    fp->fh_sin.sin_port = htons(NFS_PORT);
+  }
+
+  /*
+   * Use native path like the rest of amd (cf. RFC 2054, 6.1).
+   */
+  wnfs_path = (char *) xmalloc(strlen(fp->fh_path) + 2);
+  wnfs_path[0] = 0x80;
+  strcpy(wnfs_path + 1, fp->fh_path);
+
+  /* find the right program and lookup procedure */
+#ifdef HAVE_FS_NFS3
+  if (fp->fh_nfs_version == NFS_VERSION3) {
+    proc = NFSPROC3_LOOKUP;
+    xdr_fn = (XDRPROC_T_TYPE) xdr_LOOKUP3args;
+    argp = &args3;
+    /* WebNFS public file handle */
+    args3.what.dir.fh3_length = 0;
+    args3.what.name = wnfs_path;
+  } else {
+#endif /* HAVE_FS_NFS3 */
+    proc = NFSPROC_LOOKUP;
+    xdr_fn = (XDRPROC_T_TYPE) xdr_diropargs;
+    argp = &args;
+    /* WebNFS public file handle */
+    memset(&args.da_fhandle, 0, NFS_FHSIZE);
+    args.da_name = wnfs_path;
+#ifdef HAVE_FS_NFS3
+  }
+#endif /* HAVE_FS_NFS3 */
+
+  plog(XLOG_INFO, "webnfs_lookup: NFS version %d", (int) fp->fh_nfs_version);
+
+  rpc_msg_init(&wnfs_msg, NFS_PROGRAM, fp->fh_nfs_version, proc);
+  len = make_rpc_packet(iobuf,
+                       sizeof(iobuf),
+                       proc,
+                       &wnfs_msg,
+                       argp,
+                       (XDRPROC_T_TYPE) xdr_fn,
+                       nfs_auth);
+
+  if (len > 0) {
+    error = fwd_packet(MK_RPC_XID(RPC_XID_WEBNFS, fp->fh_id),
+                      iobuf,
+                      len,
+                      &fp->fh_sin,
+                      &fp->fh_sin,
+                      (opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
+                      fun);
+  } else {
+    error = -len;
+  }
+
+  XFREE(wnfs_path);
+  return error;
+}
+
+
 /*
  * NFS needs the local filesystem, remote filesystem
  * remote hostname.
@@ -810,6 +953,9 @@ nfs_umounted(mntfs *mf)
   if (mf->mf_error || mf->mf_refc > 1)
     return;
 
+  /*
+   * No need to inform mountd when WebNFS is in use.
+   */
   if (mf->mf_flags & MFF_WEBNFS)
     return;
 
index 5f13cf9ddbc5178dc79b8d44dc07a7144ec7f8df..66fbb6ee8c28aca795808e87b72201f6972d1892 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: rpc_fwd.c,v 1.16 2003/10/02 17:13:22 ro Exp $
+ * $Id: rpc_fwd.c,v 1.17 2003/10/09 20:33:46 ro Exp $
  *
  */
 
@@ -254,6 +254,9 @@ fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct so
   case RPC_XID_NFSPING:
     dlog("Sending NFS ping %#x", type_id);
     break;
+  case RPC_XID_WEBNFS:
+    dlog("Sending WebNFS lookup %#x", type_id);
+    break;
   default:
     dlog("UNKNOWN RPC XID %#x", type_id);
     break;
@@ -439,6 +442,9 @@ again:
   case RPC_XID_NFSPING:
     dlog("Receiving NFS ping %#x", pkt_xid);
     break;
+  case RPC_XID_WEBNFS:
+    dlog("Receiving WebNFS lookup %#x", pkt_xid);
+    break;
   default:
     dlog("UNKNOWN RPC XID %#x", pkt_xid);
     break;
index 446a8f658ce3a6e3ad9f8f07d473ee85c926709d..61e87cebb0c85b9d7e712e979cb9f294c955b7a4 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: srvr_nfs.c,v 1.32 2003/10/01 02:45:12 ib42 Exp $
+ * $Id: srvr_nfs.c,v 1.33 2003/10/09 20:33:46 ro Exp $
  *
  */
 
@@ -272,6 +272,12 @@ recompute_portmap(fserver *fs)
   int error;
   u_long mnt_version;
 
+  /*
+   * No portmap calls for pure WebNFS servers.
+   */
+  if (fs->fs_flags & FSF_WEBNFS)
+    return;
+
   if (nfs_auth)
     error = 0;
   else
@@ -286,7 +292,8 @@ recompute_portmap(fserver *fs)
   if (fs->fs_version == 0)
     plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
 
-  plog(XLOG_INFO, "recompute_portmap: NFS version %d", (int) fs->fs_version);
+  plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
+       (int) fs->fs_version, fs->fs_host);
 #ifdef HAVE_FS_NFS3
   if (fs->fs_version == NFS_VERSION3)
     mnt_version = MOUNTVERS3;
@@ -618,6 +625,7 @@ find_nfs_srvr(mntfs *mf)
   u_long best_nfs_version = 0;
   char *nfs_proto = NULL;      /* no IP protocol either */
   int nfs_port = 0;
+  int nfs_port_opt = 0;
   int fserver_is_down = 0;
 
   /*
@@ -744,16 +752,33 @@ find_nfs_srvr(mntfs *mf)
 #endif /* not HAVE_FS_NFS3 */
 
 
-  if (amu_hasmntopt(&mnt, "webnfs")) {
-    plog(XLOG_INFO, "webnfs option used, NOT contacting the portmapper on %s", host);
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) {
+    /*
+     * Use WebNFS to obtain file handles.
+     */
     mf->mf_flags |= MFF_WEBNFS;
+    plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s",
+        MNTTAB_OPT_PUBLIC, host);
+    /*
+     * Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7).
+     */
     if (!nfs_version) {
-      plog(XLOG_INFO, "No NFS version specified, will use NFSv2");
+#ifdef HAVE_FS_NFS3
+      nfs_version = NFS_VERSION3;
+#else /* not HAVE_FS_NFS3 */
       nfs_version = NFS_VERSION;
+#endif /* not HAVE_FS_NFS3 */
+      plog(XLOG_INFO, "No NFS version specified, will use NFSv%d",
+          (int) nfs_version);
     }
     if (!nfs_proto) {
-      plog(XLOG_INFO, "No NFS protocol transport specified, will use udp");
+#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
+      nfs_proto = "tcp";
+#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
       nfs_proto = "udp";
+#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+      plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
+          nfs_proto);
     }
   } else {
     /*
@@ -809,8 +834,21 @@ find_nfs_srvr(mntfs *mf)
     }
   }
 
+  /*
+   * Determine the NFS port.
+   *
+   * A valid "port" mount option overrides anything else.
+   * If the port has been determined from the portmapper, use that.
+   * Default to NFS_PORT otherwise (cf. RFC 2054, 3).
+   */
+  nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT);
+  if (nfs_port_opt > 0)
+    nfs_port = htons(nfs_port_opt);
   if (!nfs_port)
     nfs_port = htons(NFS_PORT);
+
+  dlog("find_nfs_srvr: using port %d for nfs on %s",
+       (int) ntohs(nfs_port), host);
   ip->sin_port = nfs_port;
 
 no_dns:
@@ -833,6 +871,13 @@ no_dns:
       if (hp && fs->fs_ip)
        memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
 
+      /*
+       * If the new file systems doesn't use WebNFS, the nfs pings may
+       * try to contact the portmapper.
+       */
+      if (!(mf->mf_flags & MFF_WEBNFS))
+       fs->fs_flags &= ~FSF_WEBNFS;
+
       /*
        * following if statement from Mike Mitchell
        * <mcm@unx.sas.com>
@@ -885,6 +930,8 @@ no_dns:
     mf->mf_flags |= MFF_ERROR;
     mf->mf_error = ENOENT;
   }
+  if (mf->mf_flags & MFF_WEBNFS)
+    fs->fs_flags |= FSF_WEBNFS;
   fs->fs_version = nfs_version;
   fs->fs_proto = nfs_proto;
   fs->fs_type = MNTTAB_TYPE_NFS;
index 7ccd072d3781e350eb4201c0927b21190af7ed3b..61e0fa5dbe1f3d185cb70c2f2442e9c5e2b3223e 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: nfs_prot_linux.h,v 1.17 2002/12/27 22:44:00 ezk Exp $
+ * $Id: nfs_prot_linux.h,v 1.18 2003/10/09 20:33:46 ro Exp $
  *
  */
 
@@ -258,6 +258,40 @@ struct nfs_args {
 typedef struct nfs_args nfs_args_t;
 
 #ifdef HAVE_FS_NFS3
+#define NFSPROC3_LOOKUP ((u_long) 3)
+enum nfsstat3 {
+       NFS3_OK = 0,
+       NFS3ERR_PERM = 1,
+       NFS3ERR_NOENT = 2,
+       NFS3ERR_IO = 5,
+       NFS3ERR_NXIO = 6,
+       NFS3ERR_ACCES = 13,
+       NFS3ERR_EXIST = 17,
+       NFS3ERR_XDEV = 18,
+       NFS3ERR_NODEV = 19,
+       NFS3ERR_NOTDIR = 20,
+       NFS3ERR_ISDIR = 21,
+       NFS3ERR_INVAL = 22,
+       NFS3ERR_FBIG = 27,
+       NFS3ERR_NOSPC = 28,
+       NFS3ERR_ROFS = 30,
+       NFS3ERR_MLINK = 31,
+       NFS3ERR_NAMETOOLONG = 63,
+       NFS3ERR_NOTEMPTY = 66,
+       NFS3ERR_DQUOT = 69,
+       NFS3ERR_STALE = 70,
+       NFS3ERR_REMOTE = 71,
+       NFS3ERR_BADHANDLE = 10001,
+       NFS3ERR_NOT_SYNC = 10002,
+       NFS3ERR_BAD_COOKIE = 10003,
+       NFS3ERR_NOTSUPP = 10004,
+       NFS3ERR_TOOSMALL = 10005,
+       NFS3ERR_SERVERFAULT = 10006,
+       NFS3ERR_BADTYPE = 10007,
+       NFS3ERR_JUKEBOX = 10008
+};
+typedef enum nfsstat3 nfsstat3;
+
 typedef struct {
   u_int fhandle3_len;
   char *fhandle3_val;
@@ -301,6 +335,44 @@ struct nfs_fh3 {
   } fh3_u;
 };
 typedef struct nfs_fh3 am_nfs_fh3;
+
+typedef char *filename3;
+
+struct diropargs3 {
+       am_nfs_fh3 dir;
+       filename3 name;
+};
+typedef struct diropargs3 diropargs3;
+
+struct LOOKUP3args {
+       diropargs3 what;
+};
+typedef struct LOOKUP3args LOOKUP3args;
+
+struct LOOKUP3resok {
+       am_nfs_fh3 object;
+#if 0
+       post_op_attr obj_attributes;
+       post_op_attr dir_attributes;
+#endif
+};
+typedef struct LOOKUP3resok LOOKUP3resok;
+
+struct LOOKUP3resfail {
+#if 0
+       post_op_attr dir_attributes;
+#endif
+};
+typedef struct LOOKUP3resfail LOOKUP3resfail;
+
+struct LOOKUP3res {
+       nfsstat3 status;
+       union {
+               LOOKUP3resok ok;
+               LOOKUP3resfail fail;
+       } res_u;
+};
+typedef struct LOOKUP3res LOOKUP3res;
 #endif /* HAVE_FS_NFS3 */
 
 /*
index b333406c5fcb181d6822bce1d25a656734b8cd1e..1f0ec024ccb376bceef35159bbf2c538a7142748 100644 (file)
@@ -53,7 +53,7 @@ AH_BOTTOM([
 dnl
 dnl AC_CONFIG_AUX_DIR(m4)
 AC_PREREQ(2.52)
-AC_REVISION($Revision: 1.64 $)
+AC_REVISION($Revision: 1.65 $)
 AC_COPYRIGHT([Copyright (c) 1997-2003 Erez Zadok])
 dnl find out system type
 AC_MSG_NOTICE(*** SYSTEM TYPES ***)
@@ -342,6 +342,7 @@ AC_CHECK_FUNCS(                     \
        xdr_createargs          \
        xdr_dirlist             \
        xdr_diropargs           \
+       xdr_diropargs3          \
        xdr_diropokres          \
        xdr_diropres            \
        xdr_dirpath             \
@@ -352,18 +353,25 @@ AC_CHECK_FUNCS(                   \
        xdr_fhandle             \
        xdr_fhstatus            \
        xdr_filename            \
+       xdr_filename3           \
        xdr_ftype               \
        xdr_groupnode           \
        xdr_groups              \
        xdr_linkargs            \
+       xdr_LOOKUP3args         \
+       xdr_LOOKUP3res          \
+       xdr_LOOKUP3resfail      \
+       xdr_LOOKUP3resok        \
        xdr_mountbody           \
        xdr_mountlist           \
        xdr_mountres3           \
        xdr_name                \
        xdr_nfs_fh              \
+       xdr_nfs_fh3             \
        xdr_nfscookie           \
        xdr_nfspath             \
        xdr_nfsstat             \
+       xdr_nfsstat3            \
        xdr_nfstime             \
        xdr_pointer             \
        xdr_readargs            \
@@ -948,6 +956,7 @@ AMU_CHECK_MNTTAB_OPTS(      \
        private         \
        proplist        \
        proto           \
+       public          \
        retrans         \
        retry           \
        ro              \
index 3ec63a6bf4043fd77792d3a16661323725d7b018..d83dab6b4690a24c1fc03e2160cd517b402d0883 100644 (file)
@@ -38,7 +38,7 @@
 @c
 @c      %W% (Berkeley) %G%
 @c
-@c $Id: am-utils.texi,v 1.74 2003/10/09 19:31:13 ro Exp $
+@c $Id: am-utils.texi,v 1.75 2003/10/09 20:33:47 ro Exp $
 @c
 @setfilename am-utils.info
 
@@ -2217,7 +2217,7 @@ The NFS timeout, in tenth-seconds, before a request is retransmitted.
 
 @item vers=@var{n}
 @cindex Mount flags; vers
- Use NFS protocol version number @var{n} (can be 2 or 3).
+Use NFS protocol version number @var{n} (can be 2 or 3).
 
 @item wsize=@var{n}
 @cindex Mount flags; wsize
@@ -2248,6 +2248,16 @@ interval defaults to 30 seconds.  If the ping interval is less than zero,
 no pings are sent and the host is assumed to be always up, which can
 cause unmounts to hang.  See the @i{softlookup} option for a better alternative.
 
+@item public
+@cindex Mount flags; public
+Use WebNFS multi-component lookup on the public file handle instead of
+the mount protocol to obtain NFS file handles, as documented in the
+WebNFS Client Specification, RFC 2054.  This means that @i{Amd} will not
+attempt to contact the remote portmapper or remote mountd daemon, and
+will only connect to the well-known NFS port 2049 or the port specified
+with the @i{port} mount option, thus making it easier to use NFS through
+a firewall.
+
 @item retry=@var{n}
 @cindex Mount flags; retry=@var{n}
 The number of times to retry the mount system call.
@@ -2283,26 +2293,6 @@ has failed.  In fact the interval is extended before the unmount is
 attempted, to avoid thrashing.  The default value is 120 seconds (two
 minutes) or as set by the @code{-w} command line option.
 
-@item webnfs
-@cindex Mount flags; webnfs
-Tells amd to mount the public share from the remote server (rfs is
-effectively ignored), using the public filehandle as documented in the
-WebNFS RFC. This means that amd will not attempt to contact the remote
-portmapper or remote mountd daemon, and will only connect to the
-well-known NFS port 2049, thus making it easier to use NFS through a
-firewall.
-
-Caveats:
-- since here is only one public filehandle, it necessarily means that
-only one share per fileserver can be mounted via WebNFS. This is a
-limitation of the WebNFS specification, not of amd itself.
-
-- since there is no portmapper communication, amd will not attempt any
-sort of discovery of remote server capabilities, and will default to
-using NFSv2/UDP. It is the admin's responsibility to alter this
-behavior by explicitly specifying the desired NFS version and protocol
-within the mount options for each webnfs map entry.
-
 @item xlatecookie
 @cindex Mount flags; xlatecookie
 Translate directory cookies between 32-long and 64-long lengths.
index d0a3bfe8962b36b0c537ed4e65ac88637c123151..9bba83c19db44740af608dc20dc41c4d03bdf9f3 100644 (file)
 # define MNTTAB_OPT_PORT "port"
 #endif /* not MNTTAB_OPT_PORT */
 
+#ifndef MNTTAB_OPT_PUBLIC
+# define MNTTAB_OPT_PUBLIC "public"
+#endif /* not MNTTAB_OPT_PUBLIC */
+
 #ifndef MNTTAB_OPT_RETRANS
 # define MNTTAB_OPT_RETRANS "retrans"
 #endif /* not MNTTAB_OPT_RETRANS */
index 73160bf1fe2cf6cb4ccbc30d7fac264ef5239a29..7db45795f6315f9064624ef6e683561e6d142963 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: am_utils.h,v 1.53 2003/10/02 16:29:29 ro Exp $
+ * $Id: am_utils.h,v 1.54 2003/10/09 20:33:48 ro Exp $
  *
  */
 
@@ -155,6 +155,7 @@ extern int umount_fs(char *mntdir, const char *mnttabname, int on_autofs);
 #define        RPC_XID_PORTMAP         0
 #define        RPC_XID_MOUNTD          1
 #define        RPC_XID_NFSPING         2
+#define        RPC_XID_WEBNFS          3
 #define        RPC_XID_MASK            (0x0f)  /* 16 id's for now */
 #define        MK_RPC_XID(type_id, uniq)       ((type_id) | ((uniq) << 4))
 
index f44e825a8374d218409e47a16b36bbfb59b0a70e..a300ace52aea76d6a49b2207ec20251dab405b15 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: am_xdr_func.h,v 1.10 2002/12/27 22:44:09 ezk Exp $
+ * $Id: am_xdr_func.h,v 1.11 2003/10/09 20:33:48 ro Exp $
  *
  */
 
@@ -180,4 +180,34 @@ bool_t xdr_symlinkargs(XDR *xdrs, nfssymlinkargs *objp);
 #ifndef HAVE_XDR_WRITEARGS
 bool_t xdr_writeargs(XDR *xdrs, nfswriteargs *objp);
 #endif /* not HAVE_XDR_WRITEARGS */
+
+/*
+ * NFS3 XDR FUNCTIONS:
+ */
+#ifdef HAVE_FS_NFS3
+# ifndef HAVE_XDR_DIROPARGS3
+bool_t xdr_diropargs3(XDR *xdrs, diropargs3 *objp);
+#endif /* not HAVE_XDR_DIROPARGS3 */
+# ifndef HAVE_XDR_FILENAME3
+bool_t xdr_filename3(XDR *xdrs, filename3 *objp);
+# endif /* not HAVE_XDR_FILENAME3 */
+# ifndef HAVE_XDR_LOOKUP3ARGS
+bool_t xdr_LOOKUP3args(XDR *xdrs, LOOKUP3args *objp);
+# endif /* not HAVE_XDR_LOOKUP3ARGS */
+# ifndef HAVE_XDR_LOOKUP3RES
+bool_t xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp);
+# endif /* not HAVE_XDR_LOOKUP3RES */
+# ifndef HAVE_XDR_LOOKUP3RESFAIL
+bool_t xdr_LOOKUP3resfail(XDR *xdrs, LOOKUP3resfail *objp);
+# endif /* not HAVE_XDR_LOOKUP3RESFAIL */
+# ifndef HAVE_XDR_LOOKUP3RESOK
+bool_t xdr_LOOKUP3resok(XDR *xdrs, LOOKUP3resok *objp);
+# endif /* not HAVE_XDR_LOOKUP3RESOK */
+# ifndef HAVE_XDR_NFS_FH3
+bool_t xdr_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp);
+# endif /* not HAVE_XDR_NFS_FH3 */
+# ifndef HAVE_XDR_NFSSTAT3
+bool_t xdr_nfsstat3(XDR *xdrs, nfsstat3 *objp);
+# endif /* not HAVE_XDR_NFSSTAT3 */
+#endif /* HAVE_FS_NFS3 */
 #endif /* not _AM_XDR_FUNC_H */
index fefceada9c6c99c0fb23f327d04ff2b6c0c51959..b563c2418e16790ac695b558f151d733926efe3a 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: xdr_func.c,v 1.17 2002/12/29 01:09:08 ezk Exp $
+ * $Id: xdr_func.c,v 1.18 2003/10/09 20:33:48 ro Exp $
  *
  */
 
@@ -972,3 +972,156 @@ xdr_writeargs(XDR *xdrs, nfswriteargs *objp)
   return (TRUE);
 }
 #endif /* not HAVE_XDR_WRITEARGS */
+
+
+/*
+ * NFS V3 XDR FUNCTIONS:
+ */
+#ifdef HAVE_FS_NFS3
+# ifndef HAVE_XDR_DIROPARGS3
+bool_t
+xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_diropargs3:");
+
+  if (!xdr_nfs_fh3(xdrs, &objp->dir))
+    return (FALSE);
+  if (!xdr_filename3(xdrs, &objp->name))
+    return (FALSE);
+  return (TRUE);
+}
+#endif /* not HAVE_XDR_DIROPARGS3 */
+
+
+# ifndef HAVE_XDR_FILENAME3
+bool_t
+xdr_filename3(XDR *xdrs, filename3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_filename3:");
+
+  if (!xdr_string(xdrs, objp, ~0))
+    return (FALSE);
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_FILENAME3 */
+
+
+# ifndef HAVE_XDR_LOOKUP3ARGS
+bool_t
+xdr_LOOKUP3args(XDR *xdrs, LOOKUP3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_LOOKUP3args:");
+
+  if (!xdr_diropargs3(xdrs, &objp->what))
+    return (FALSE);
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_LOOKUP3ARGS */
+
+
+# ifndef HAVE_XDR_LOOKUP3RES
+bool_t
+xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_LOOKUP3res:");
+
+  if (!xdr_nfsstat3(xdrs, &objp->status))
+    return (FALSE);
+  switch (objp->status) {
+  case NFS3_OK:
+    if (!xdr_LOOKUP3resok(xdrs, &objp->res_u.ok))
+      return (FALSE);
+    break;
+  default:
+    if (!xdr_LOOKUP3resfail(xdrs, &objp->res_u.fail))
+      return (FALSE);
+    break;
+  }
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_LOOKUP3RES */
+
+
+# ifndef HAVE_XDR_LOOKUP3RESFAIL
+bool_t
+xdr_LOOKUP3resfail(XDR *xdrs, LOOKUP3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_LOOKUP3resfail:");
+
+  /*
+   * Don't xdr post_op_attr: amd doesn't need them, but they require many
+   * additional xdr functions.
+   */
+#if 0
+  if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+    return (FALSE);
+#endif
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_LOOKUP3RESFAIL */
+
+
+# ifndef HAVE_XDR_LOOKUP3RESOK
+bool_t
+xdr_LOOKUP3resok(XDR *xdrs, LOOKUP3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_LOOKUP3resok:");
+
+  if (!xdr_nfs_fh3(xdrs, &objp->object))
+    return (FALSE);
+  /*
+   * Don't xdr post_op_attr: amd doesn't need them, but they require many
+   * additional xdr functions.
+   */
+#if 0
+  if (!xdr_post_op_attr(xdrs, &objp->obj_attributes))
+    return (FALSE);
+  if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+    return (FALSE);
+#endif
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_LOOKUP3RESOK */
+
+
+# ifndef HAVE_XDR_NFS_FH3
+bool_t
+xdr_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_nfs_fh3:");
+
+  /*
+   * nfs_fh3 used by the kernel differs from the definition generated from
+   * nfs_prot.x, so cannot use the generated xdr_nfs_fh3().
+   */
+  if (!xdr_u_int(xdrs, &objp->fh3_length))
+    return (FALSE);
+  if (objp->fh3_length > NFS3_FHSIZE)
+    return (FALSE);
+  if (!xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length))
+    return (FALSE);
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_NFS_FH3 */
+
+
+# ifndef HAVE_XDR_NFSSTAT3
+bool_t
+xdr_nfsstat3(XDR *xdrs, nfsstat3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_nfsstat3:");
+
+  if (!xdr_enum(xdrs, (enum_t *)objp))
+    return (FALSE);
+  return (TRUE);
+}
+# endif /* not HAVE_XDR_NFSSTAT3 */
+#endif /* not HAVE_FS_NFS3 */