Previous section.

Protocols for Interworking: XNFS, Version 3W
Copyright © 1998 The Open Group

WebNFS Extensions

Introduction

The WebNFS extensions are an optional set of extensions to the NFS protocol. They provide additional semantics that can be applied to versions 2 and 3 of the protocol to: eliminate the overhead of PORTMAP and MOUNT protocols, make the protocol easier to use where firewall transit is required, and reduce the number of LOOKUP requests required to identify a particular file on the server.

This Appendix describes the changes to an NFS implementation that are needed to support the WebNFS extensions. It also describes NFS URLs, which can be used by WebNFS clients, including web browsers, to specify files on WebNFS servers.

TCP versus UDP

The NFS protocol is most well known for its use of UDP, which performs acceptably on local area networks. However, on wide area networks with error prone, high-latency connections and bandwidth contention, TCP is well respected for its congestion control and superior error handling. A growing number of NFS implementations now support the NFS protocol over TCP connections.

Version 3 of the NFS protocol is particularly well matched to the use of TCP as a transport protocol. Version 3 removes the arbitrary 8k transfer size limit of version 2, allowing the READ or WRITE of very large streams of data over a TCP connection. Note that version 2 is also supported on TCP connections, though the benefits of TCP data streaming will not be as great.

A WebNFS client must first attempt to connect to its server with a TCP connection. If the server refuses the connection, the client should attempt to use UDP.

Well-Known Port

While Internet protocols are generally identified by registered port number assignments, RPC-based protocols register a 32-bit program number and a dynamically assigned port with the portmap service which is registered on the well-known port 111. Since the NFS protocol is RPC-based, NFS servers register their port assignment with the portmap service.

NFS servers are constrained by a requirement to re-register at the same port after a server crash and recovery so that clients can recover simply by retransmitting an RPC request until a response is received. This is simpler than the alternative of having the client repeatedly check with the portmap service for a new port assignment. NFS servers typically achieve this port invariance by registering a constant port assignment, 2049, for both UDP and TCP.

To avoid the overhead of contacting the server's portmap service, and to facilitate transit through packet filtering firewalls, WebNFS clients optimistically assume that NFS servers register on port 2049. Most NFS servers use this port assignment already, so this client optimism is well justified.

Server Port Monitoring

Some NFS servers accept requests only from reserved UDP or TCP ports, that is, port numbers below 1024. These privileged ports are available only to UNIX processes with Super-user permissions. Requests that do not originate from the range of reserved ports are rejected. This is an optimistic way of preventing direct access to the server from user processes that may attempt to spoof AUTH_UNIX RPC credentials.

WebNFS clients are not required to use reserved ports. This means that a WebNFS server must not check the originating port for requests to filesystems which are made available to WebNFS clients.

Public Filehandle

NFS filehandles are normally created by the server and used to identify uniquely a particular file or directory on the server. The client does not normally create filehandles or have any knowledge of the contents of a filehandle.

The public filehandle is an an exception. It is an NFS filehandle with a reserved value and special semantics. A WebNFS client uses the public filehandle as an initial filehandle rather than using the MOUNT protocol. Since versions 2 and 3 of the NFS protocol have different filehandle formats, the public filehandle is defined differently for each.

NFS Version 2 Public Filehandle

A version 2 filehandle is an opaque value occupying 32 octets. A version 2 public filehandle has a zero in each octet (that is, all zeros).

1                                                             32
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

NFS Version 3 Public Filehandle

A version 3 filehandle is defined in as a variable length opaque value occupying up to 64 octets. The length of the filehandle is indicated by an integer value contained in a 4 octet value which describes the number of valid octets that follow. A version 3 public filehandle has a length of zero.

0 0 0 0

Multi-Component Lookup

Normally the NFS LOOKUP request (version 2 or 3) takes a directory filehandle along with the name of a directory member, and returns the filehandle of the directory member. If a client needs to evaluate a pathname that contains a sequence of components, then beginning with the directory filehandle of the first component it must issue a series of LOOKUP requests one component at a time. For example, evaluation of the path "a/b/c" will generate separate LOOKUP requests for each component of the pathname "a", "b", and "c".

A LOOKUP request that uses the public filehandle can provide a pathname containing multiple components. The server is expected to evaluate the entire pathname and return a filehandle for the final component.

For example, rather than evaluate the path "a/b/c" as:

LOOKUP FH=0x0 "a" -> <- FH=0x1 LOOKUP FH=0x1 "b" -> <- FH=0x2 LOOKUP FH=0x2 "c" -> <- FH=0x3

Relative to the public filehandle, these 3 LOOKUP requests can be replaced by a single multi-component lookup:

LOOKUP FH=0x0 "a/b/c" -> <- FH=0x3

Multi-component lookup is supported only for LOOKUP requests relative to the public filehandle.

The url-path of the NFS URL (see Absolute versus Relative Pathname must be evaluated as a multi-component lookup. This implies that the path components are delimited by slashes, and the characters that make up the path must be in the printable US-ASCII character set.

If the url-path is empty, the client must send a multi-component lookup for the pathname "." (dot).

Canonical Path versus Native Path

If the pathname in a multi-component LOOKUP request begins with an ASCII character, then it must be a canonical path. A canonical path is a hierarchically-related, slash-separated sequence of components, <directory>/<directory>/.../<name>. Occurrences of the "/" character within a component must be escaped using the escape code %2f. Non-ASCII characters within components must also be escaped using the "%" character to introduce a 2-digit hexadecimal code. Occurrences of the "%" character that do not introduce an encoded character must themselves be encoded with %25.

If the first character of the path is a slash, then the canonical path is evaluated relative to the server's root directory. If the first character is not a slash, then the path is evaluated relative to the directory with which the public filehandle is associated.

Not all WebNFS servers can support arbitrary use of absolute paths. Clearly, the server cannot return a filehandle if the path identifies a file or directory that is not exported by the server. In addition, servers need not return a filehandle if the path names a file or directory in an exported filesystem different from the one that is associated with the public filehandle.

If the first character of the path is 0x80 (non-ASCII), then the following character is the first in a native path. A native path conforms to the normal pathname syntax of the server. For example:

Lookup for Canonical Path:

LOOKUP FH=0x0 "/a/b/c"

Lookup for Native Path:

LOOKUP FH=0x0 0x80 "a:b:c"

NFS URL

An NFS URL is based on the Common Internet Scheme Syntax described in Section 3.1 of RFC 1738. It has the general form:
nfs://<host>:<port>/<url-path>

The :<port> part is optional. If omitted then port 2049 is assumed. The <url-path> is also optional. If it is omitted, then the "/" between <host>:<port> and <url-path> may also be omitted.

The <url-path> is a hierarchical directory path of the form

<directory>/<directory>/<directory>/.../<name>

The <url-path> must consist only of characters within the US-ASCII character set. Within a <directory> or <name> component, the character "/" is reserved and must be encoded as described in Section 2.2 of RFC 1738. If <url-path> is omitted, it must default to the path "." (dot).

When presented with an NFS URL, a client must use the WebNFS technique described in this document to bind to the server, and evaluate the pathname using the public filehandle and multi-component lookup.

Absolute versus Relative Pathname

A pathname that begins with a slash character is considered absolute and will be evaluated relative to the server's root. A pathname that does not begin with a slash is relative and will be evaluated relative to the directory with which the public filehandle is associated.

Note that the "/" in an NFS URL that delimits the <host>:<port> from the <url-path> is not considered part of the pathname. For example, if the public filehandle is associated with the server's directory "/a/b/c" then the URL:

nfs://server/d/e/f

will be evaluated with a relative multi-component lookup of the path "d/e/f" relative to the server's directory "/a/b/c", while the URL:

nfs://server//a/b/c/d/e/f

will locate the same file with an absolute multi-component lookup of the path "/a/b/c/d/e/f" relative to the server's filesystem root. Notice that a double slash is required at the beginning of the path; the first slash is the URL delimiter between the <host>:<port> and the <url-path>, and the second slash is the first character of <url-path>.

Not all WebNFS servers can support arbitrary use of absolute paths. Clearly, the server must not return a filehandle if the path identifies a file or directory that is not exported by the server. In addition, servers need not return a filehandle if the path names a file or directory in an exported filesystem different from the one that is associated with the public filehandle.

Symbolic Links

The NFS protocol supports symbolic links, which are the filesystem equivalent of a relative URL. If a WebNFS client retrieves a filehandle for a symbolic link (as indicated by the file type attribute) then it should send a READLINK request to the server to retrieve the path comprising the symbolic link.

This path should then be combined with the URL which referenced the symbolic link according to the rules described in RFC 1808. If the relative URL in the symbolic link text is to be resolved successfully then it must contain only ASCII characters and conform to the syntax described in RFC 1808. Note that this allows a symbolic link to contain an entire URL and it may specify a scheme that is not necessarily an NFS URL (for example, HTTP).

An exception to RFC 1808 rules applies in the case of an absolute symbolic link, where the path begins with a "/". RFC 1808 describes a method for resolving relative URLs with respect to the base URL. Given a base URL of "nfs://s/a/b/c" which references a symbolic link with contents "/a/b/c/d", the method would yield a URL "nfs://s/a/b/c/" which would be correct only if the public filehandle were co-located with the server's filesystem root.

If the symbolic link begins with a slash, then after resolving a relative URL derived from the symbolic link contents according to the method in RFC 1808, the client must insert an additional slash in front of the path so that the server will evaluate the path relative to the server's root, rather than the public filehandle directory. This variation from the normal method of resolving a relative URL applies only to handling of symbolic links. The additional slash must not be inserted if the relative URL was embedded in a document or other encapsulating entity.

For example, if the symbolic link is named by the URL:

nfs://server/a/b

then the the following examples show how a new URL can be formed from the symbolic link text:

c = nfs://server/a/c c/d = nfs://server/a/c/d /c/d = nfs://server//c/d nfs://server2/a/b = nfs://server2/a/b

Export Spanning Pathnames

The server may evaluate a pathname, either through a multi-component LOOKUP or as a symbolic link embedded in a pathname, that references a file or directory outside of the exported hierarchy.

Clearly, if the destination of the path is not in an exported filesystem, then the server must return an error to the client.

Many NFS server implementations rely on the MOUNT protocol for checking access to exported filesystems, and their NFS server does no access checking. The NFS server assumes that the filehandle does double duty: identifying a file as well as being a security token. Since WebNFS clients do not normally use the MOUNT protocol, a server that relies on MOUNT checking cannot automatically grant access to another exported filesystem at the destination of a spanning path. These servers must return an error.

For example: suppose the server exports two filesystems. One is associated with the public filehandle:

/export/this (public filehandle) /export/that

The server receives a LOOKUP request with the public filehandle that identifies a file or directory in the other exported filesystem:

LOOKUP 0x0 "../that/file"

or:

LOOKUP 0x0 "/export/that/file"

Even though the pathname destination is in an exported filesystem, the server cannot return a filehandle without an assurance that the client's use of this filehandle will be authorized.

Servers that check client access to an export on every NFS request have more flexibility. These servers can return filehandles for paths that span exports since the client's use of the filehandle for the destination filesystem will be checked by the NFS server.

Location of Public Filehandle

A server administrator can associate the public filehandle with any file or directory. For instance, a WebNFS server administrator could attach the public filehandle to the root of an anonymous FTP archive, so that anonymous FTP pathnames could be used to identify files in the FTP hierarchy.

On servers that support spanning paths, the public filehandle need not necessarily be attached to an exported directory, though a successful LOOKUP relative to the public filehandle must identify a file or directory that is exported.

For instance, if an NFS server exports a directory "/export/foo" and the public filehandle is attached to the server's root directory, then a LOOKUP of "export/foo" relative to the public filehandle will return a valid file handle but a LOOKUP of "export" will return an access error since the server's "/export" directory is not exported.

Contacting the Server

WebNFS clients should be optimistic in assuming that the server supports the WebNFS extensions, but must be capable of fallback to conventional methods for server access if the server does not support them.

The client should start with the assumption that the server supports:

If these assumptions are not met, the client should fall back gracefully with a minimum number of messages. The following steps are recommended:

  1. Attempt to create a TCP connection to the server's port 2049.

    If the connection fails then assume that a request sent over UDP will work. Use UDP port 2049.

    Do not use the PORTMAP protocol to determine the server's port unless the server does not respond to port 2049 for both TCP and UDP.

  2. Assume WebNFS and V3 are supported. Send an NFS version 3 LOOKUP, with the public filehandle for the requested pathname.

    If the server returns an RPC PROG_MISMATCH error then assume that version 3 is not supported. Retry the LOOKUP with a version 2 public filehandle.

    Note:
    The first call may not necessarily be a LOOKUP if the operation is directed at the public filehandle itself, for example, a READDIR or READDIRPLUS of the directory that is associated with the public filehandle.

    If the server returns an NFS3ERR_STALE, NFS3ERR_INVAL, or NFS3ERR_BADHANDLE error, then assume that the server does not support the WebNFS extensions because it does not recognize the public filehandle. The client must use the server's portmap service to locate and use the MOUNT protocol to obtain an initial filehandle for the requested path.

WebNFS clients can benefit by caching information about the server:

If the server does not support public filehandles, the client may choose to cache the port assignment of the MOUNT service as well as previously used pathnames and their filehandles.

Mount Protocol

The NFS URL may have limited use for naming files on servers that do not support the public filehandle and multi-component lookup.

If the server returns an NFS3ERR_STALE, NFS3ERR_INVAL, or NFS3ERR_BADHANDLE error in response to the client's use of a public filehandle, then the client should attempt to resolve the <url-path> to a filehandle using the MOUNT protocol.

Note that the pathname sent to the server in the MOUNTPROC_MNT request is assumed to be a server native path, rather than a slash-separated path described by RFC 1738. Hence, the MOUNT protocol can reasonably be expected to map a <url-path> to a filehandle only on servers that support slash-separated ASCII native paths. In general, servers that do not support WebNFS access or slash-separated ASCII native paths should not advertise NFS URLs.

At this point the client must already have some indication as to which version of the NFS protocol is supported on the server. Since the filehandle format differs between NFS versions 2 and 3, the client must select the appropriate version of the MOUNT protocol. MOUNT versions 1 and 2 return only NFS version 2 filehandles, whereas MOUNT version 3 returns NFS version 3 filehandles.

Unlike the NFS service, the MOUNT service is not registered on a well-known port. The client must use the PORTMAP service to locate the server's MOUNT port before it can transmit a MOUNTPROC_MNT request to retrieve the filehandle corresponding to the requested path. This is described in the following diagram:

NFS servers commonly use a client's successful MOUNTPROC_MNT request as an indication that the client has mounted the filesystem and may maintain this information in a file that lists the filesystems that clients currently have mounted. This information is removed from the file when the client transmits a MOUNTPROC_UMNT request. Upon receiving a successful reply to a MOUNTPROC_MNT request, a WebNFS client should send a MOUNTPROC_UMNT request to prevent an accumulation of mounted records on the server.


Why not acquire a nicely bound hard copy?
Click here to return to the publication details or order a copy of this publication.

Contents Next section Index