The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsserver/nfs_nfsdsubs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/12.0/sys/fs/nfsserver/nfs_nfsdsubs.c 335012 2018-06-12 19:36:32Z rmacklem $");
   38 
   39 #ifndef APPLEKEXT
   40 /*
   41  * These functions support the macros and help fiddle mbuf chains for
   42  * the nfs op functions. They do things like create the rpc header and
   43  * copy data between mbuf chains and uio lists.
   44  */
   45 #include <fs/nfs/nfsport.h>
   46 
   47 extern u_int32_t newnfs_true, newnfs_false;
   48 extern int nfs_pubfhset;
   49 extern struct nfsclienthashhead *nfsclienthash;
   50 extern int nfsrv_clienthashsize;
   51 extern struct nfslockhashhead *nfslockhash;
   52 extern int nfsrv_lockhashsize;
   53 extern struct nfssessionhash *nfssessionhash;
   54 extern int nfsrv_sessionhashsize;
   55 extern int nfsrv_useacl;
   56 extern uid_t nfsrv_defaultuid;
   57 extern gid_t nfsrv_defaultgid;
   58 
   59 char nfs_v2pubfh[NFSX_V2FH];
   60 struct nfsdontlisthead nfsrv_dontlisthead;
   61 struct nfslayouthead nfsrv_recalllisthead;
   62 static nfstype newnfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
   63     NFNON, NFCHR, NFNON };
   64 extern nfstype nfsv34_type[9];
   65 #endif  /* !APPLEKEXT */
   66 
   67 static u_int32_t nfsrv_isannfserr(u_int32_t);
   68 
   69 SYSCTL_DECL(_vfs_nfsd);
   70 
   71 static int      enable_checkutf8 = 1;
   72 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_checkutf8, CTLFLAG_RW,
   73     &enable_checkutf8, 0,
   74     "Enable the NFSv4 check for the UTF8 compliant name required by rfc3530");
   75 
   76 static int    enable_nobodycheck = 1;
   77 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nobodycheck, CTLFLAG_RW,
   78     &enable_nobodycheck, 0,
   79     "Enable the NFSv4 check when setting user nobody as owner");
   80 
   81 static int    enable_nogroupcheck = 1;
   82 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_nogroupcheck, CTLFLAG_RW,
   83     &enable_nogroupcheck, 0,
   84     "Enable the NFSv4 check when setting group nogroup as owner");
   85 
   86 static char nfsrv_hexdigit(char, int *);
   87 
   88 /*
   89  * Maps errno values to nfs error numbers.
   90  * Use NFSERR_IO as the catch all for ones not specifically defined in
   91  * RFC 1094. (It now includes the errors added for NFSv3.)
   92  */
   93 static u_char nfsrv_v2errmap[NFSERR_REMOTE] = {
   94   NFSERR_PERM,  NFSERR_NOENT,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
   95   NFSERR_NXIO,  NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
   96   NFSERR_IO,    NFSERR_IO,      NFSERR_ACCES,   NFSERR_IO,      NFSERR_IO,
   97   NFSERR_IO,    NFSERR_EXIST,   NFSERR_XDEV,    NFSERR_NODEV,   NFSERR_NOTDIR,
   98   NFSERR_ISDIR, NFSERR_INVAL,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
   99   NFSERR_IO,    NFSERR_FBIG,    NFSERR_NOSPC,   NFSERR_IO,      NFSERR_ROFS,
  100   NFSERR_MLINK, NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  101   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  102   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  103   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  104   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  105   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  106   NFSERR_IO,    NFSERR_IO,      NFSERR_NAMETOL, NFSERR_IO,      NFSERR_IO,
  107   NFSERR_NOTEMPTY, NFSERR_IO,   NFSERR_IO,      NFSERR_DQUOT,   NFSERR_STALE,
  108   NFSERR_REMOTE,
  109 };
  110 
  111 /*
  112  * Maps errno values to nfs error numbers.
  113  * Although it is not obvious whether or not NFS clients really care if
  114  * a returned error value is in the specified list for the procedure, the
  115  * safest thing to do is filter them appropriately. For Version 2, the
  116  * X/Open XNFS document is the only specification that defines error values
  117  * for each RPC (The RFC simply lists all possible error values for all RPCs),
  118  * so I have decided to not do this for Version 2.
  119  * The first entry is the default error return and the rest are the valid
  120  * errors for that RPC in increasing numeric order.
  121  */
  122 static short nfsv3err_null[] = {
  123         0,
  124         0,
  125 };
  126 
  127 static short nfsv3err_getattr[] = {
  128         NFSERR_IO,
  129         NFSERR_IO,
  130         NFSERR_STALE,
  131         NFSERR_BADHANDLE,
  132         NFSERR_SERVERFAULT,
  133         NFSERR_DELAY,
  134         0,
  135 };
  136 
  137 static short nfsv3err_setattr[] = {
  138         NFSERR_IO,
  139         NFSERR_ACCES,
  140         NFSERR_PERM,
  141         NFSERR_IO,
  142         NFSERR_INVAL,
  143         NFSERR_NOSPC,
  144         NFSERR_ROFS,
  145         NFSERR_DQUOT,
  146         NFSERR_STALE,
  147         NFSERR_BADHANDLE,
  148         NFSERR_NOT_SYNC,
  149         NFSERR_SERVERFAULT,
  150         NFSERR_DELAY,
  151         0,
  152 };
  153 
  154 static short nfsv3err_lookup[] = {
  155         NFSERR_IO,
  156         NFSERR_NOENT,
  157         NFSERR_ACCES,
  158         NFSERR_NAMETOL,
  159         NFSERR_IO,
  160         NFSERR_NOTDIR,
  161         NFSERR_STALE,
  162         NFSERR_BADHANDLE,
  163         NFSERR_SERVERFAULT,
  164         NFSERR_DELAY,
  165         0,
  166 };
  167 
  168 static short nfsv3err_access[] = {
  169         NFSERR_IO,
  170         NFSERR_IO,
  171         NFSERR_STALE,
  172         NFSERR_BADHANDLE,
  173         NFSERR_SERVERFAULT,
  174         NFSERR_DELAY,
  175         0,
  176 };
  177 
  178 static short nfsv3err_readlink[] = {
  179         NFSERR_IO,
  180         NFSERR_IO,
  181         NFSERR_ACCES,
  182         NFSERR_INVAL,
  183         NFSERR_STALE,
  184         NFSERR_BADHANDLE,
  185         NFSERR_NOTSUPP,
  186         NFSERR_SERVERFAULT,
  187         NFSERR_DELAY,
  188         0,
  189 };
  190 
  191 static short nfsv3err_read[] = {
  192         NFSERR_IO,
  193         NFSERR_IO,
  194         NFSERR_NXIO,
  195         NFSERR_ACCES,
  196         NFSERR_INVAL,
  197         NFSERR_STALE,
  198         NFSERR_BADHANDLE,
  199         NFSERR_SERVERFAULT,
  200         NFSERR_DELAY,
  201         0,
  202 };
  203 
  204 static short nfsv3err_write[] = {
  205         NFSERR_IO,
  206         NFSERR_IO,
  207         NFSERR_ACCES,
  208         NFSERR_NOSPC,
  209         NFSERR_INVAL,
  210         NFSERR_FBIG,
  211         NFSERR_ROFS,
  212         NFSERR_DQUOT,
  213         NFSERR_STALE,
  214         NFSERR_BADHANDLE,
  215         NFSERR_SERVERFAULT,
  216         NFSERR_DELAY,
  217         0,
  218 };
  219 
  220 static short nfsv3err_create[] = {
  221         NFSERR_IO,
  222         NFSERR_EXIST,
  223         NFSERR_NAMETOL,
  224         NFSERR_ACCES,
  225         NFSERR_IO,
  226         NFSERR_NOTDIR,
  227         NFSERR_NOSPC,
  228         NFSERR_ROFS,
  229         NFSERR_DQUOT,
  230         NFSERR_STALE,
  231         NFSERR_BADHANDLE,
  232         NFSERR_NOTSUPP,
  233         NFSERR_SERVERFAULT,
  234         NFSERR_DELAY,
  235         0,
  236 };
  237 
  238 static short nfsv3err_mkdir[] = {
  239         NFSERR_IO,
  240         NFSERR_EXIST,
  241         NFSERR_ACCES,
  242         NFSERR_NAMETOL,
  243         NFSERR_IO,
  244         NFSERR_NOTDIR,
  245         NFSERR_NOSPC,
  246         NFSERR_ROFS,
  247         NFSERR_DQUOT,
  248         NFSERR_STALE,
  249         NFSERR_BADHANDLE,
  250         NFSERR_NOTSUPP,
  251         NFSERR_SERVERFAULT,
  252         NFSERR_DELAY,
  253         0,
  254 };
  255 
  256 static short nfsv3err_symlink[] = {
  257         NFSERR_IO,
  258         NFSERR_ACCES,
  259         NFSERR_EXIST,
  260         NFSERR_NAMETOL,
  261         NFSERR_NOSPC,
  262         NFSERR_IO,
  263         NFSERR_NOTDIR,
  264         NFSERR_ROFS,
  265         NFSERR_DQUOT,
  266         NFSERR_STALE,
  267         NFSERR_BADHANDLE,
  268         NFSERR_NOTSUPP,
  269         NFSERR_SERVERFAULT,
  270         NFSERR_DELAY,
  271         0,
  272 };
  273 
  274 static short nfsv3err_mknod[] = {
  275         NFSERR_IO,
  276         NFSERR_ACCES,
  277         NFSERR_EXIST,
  278         NFSERR_NAMETOL,
  279         NFSERR_NOSPC,
  280         NFSERR_IO,
  281         NFSERR_NOTDIR,
  282         NFSERR_ROFS,
  283         NFSERR_DQUOT,
  284         NFSERR_STALE,
  285         NFSERR_BADHANDLE,
  286         NFSERR_NOTSUPP,
  287         NFSERR_SERVERFAULT,
  288         NFSERR_DELAY,
  289         NFSERR_BADTYPE,
  290         0,
  291 };
  292 
  293 static short nfsv3err_remove[] = {
  294         NFSERR_IO,
  295         NFSERR_NOENT,
  296         NFSERR_ACCES,
  297         NFSERR_NAMETOL,
  298         NFSERR_IO,
  299         NFSERR_NOTDIR,
  300         NFSERR_ROFS,
  301         NFSERR_STALE,
  302         NFSERR_BADHANDLE,
  303         NFSERR_SERVERFAULT,
  304         NFSERR_DELAY,
  305         0,
  306 };
  307 
  308 static short nfsv3err_rmdir[] = {
  309         NFSERR_IO,
  310         NFSERR_NOENT,
  311         NFSERR_ACCES,
  312         NFSERR_NOTDIR,
  313         NFSERR_NAMETOL,
  314         NFSERR_IO,
  315         NFSERR_EXIST,
  316         NFSERR_INVAL,
  317         NFSERR_ROFS,
  318         NFSERR_NOTEMPTY,
  319         NFSERR_STALE,
  320         NFSERR_BADHANDLE,
  321         NFSERR_NOTSUPP,
  322         NFSERR_SERVERFAULT,
  323         NFSERR_DELAY,
  324         0,
  325 };
  326 
  327 static short nfsv3err_rename[] = {
  328         NFSERR_IO,
  329         NFSERR_NOENT,
  330         NFSERR_ACCES,
  331         NFSERR_EXIST,
  332         NFSERR_NAMETOL,
  333         NFSERR_XDEV,
  334         NFSERR_IO,
  335         NFSERR_NOTDIR,
  336         NFSERR_ISDIR,
  337         NFSERR_INVAL,
  338         NFSERR_NOSPC,
  339         NFSERR_ROFS,
  340         NFSERR_MLINK,
  341         NFSERR_NOTEMPTY,
  342         NFSERR_DQUOT,
  343         NFSERR_STALE,
  344         NFSERR_BADHANDLE,
  345         NFSERR_NOTSUPP,
  346         NFSERR_SERVERFAULT,
  347         NFSERR_DELAY,
  348         0,
  349 };
  350 
  351 static short nfsv3err_link[] = {
  352         NFSERR_IO,
  353         NFSERR_ACCES,
  354         NFSERR_EXIST,
  355         NFSERR_NAMETOL,
  356         NFSERR_IO,
  357         NFSERR_XDEV,
  358         NFSERR_NOTDIR,
  359         NFSERR_INVAL,
  360         NFSERR_NOSPC,
  361         NFSERR_ROFS,
  362         NFSERR_MLINK,
  363         NFSERR_DQUOT,
  364         NFSERR_STALE,
  365         NFSERR_BADHANDLE,
  366         NFSERR_NOTSUPP,
  367         NFSERR_SERVERFAULT,
  368         NFSERR_DELAY,
  369         0,
  370 };
  371 
  372 static short nfsv3err_readdir[] = {
  373         NFSERR_IO,
  374         NFSERR_ACCES,
  375         NFSERR_NOTDIR,
  376         NFSERR_IO,
  377         NFSERR_STALE,
  378         NFSERR_BADHANDLE,
  379         NFSERR_BAD_COOKIE,
  380         NFSERR_TOOSMALL,
  381         NFSERR_SERVERFAULT,
  382         NFSERR_DELAY,
  383         0,
  384 };
  385 
  386 static short nfsv3err_readdirplus[] = {
  387         NFSERR_IO,
  388         NFSERR_ACCES,
  389         NFSERR_NOTDIR,
  390         NFSERR_IO,
  391         NFSERR_STALE,
  392         NFSERR_BADHANDLE,
  393         NFSERR_BAD_COOKIE,
  394         NFSERR_NOTSUPP,
  395         NFSERR_TOOSMALL,
  396         NFSERR_SERVERFAULT,
  397         NFSERR_DELAY,
  398         0,
  399 };
  400 
  401 static short nfsv3err_fsstat[] = {
  402         NFSERR_IO,
  403         NFSERR_IO,
  404         NFSERR_STALE,
  405         NFSERR_BADHANDLE,
  406         NFSERR_SERVERFAULT,
  407         NFSERR_DELAY,
  408         0,
  409 };
  410 
  411 static short nfsv3err_fsinfo[] = {
  412         NFSERR_STALE,
  413         NFSERR_STALE,
  414         NFSERR_BADHANDLE,
  415         NFSERR_SERVERFAULT,
  416         NFSERR_DELAY,
  417         0,
  418 };
  419 
  420 static short nfsv3err_pathconf[] = {
  421         NFSERR_STALE,
  422         NFSERR_STALE,
  423         NFSERR_BADHANDLE,
  424         NFSERR_SERVERFAULT,
  425         NFSERR_DELAY,
  426         0,
  427 };
  428 
  429 static short nfsv3err_commit[] = {
  430         NFSERR_IO,
  431         NFSERR_IO,
  432         NFSERR_STALE,
  433         NFSERR_BADHANDLE,
  434         NFSERR_SERVERFAULT,
  435         NFSERR_DELAY,
  436         0,
  437 };
  438 
  439 static short *nfsrv_v3errmap[] = {
  440         nfsv3err_null,
  441         nfsv3err_getattr,
  442         nfsv3err_setattr,
  443         nfsv3err_lookup,
  444         nfsv3err_access,
  445         nfsv3err_readlink,
  446         nfsv3err_read,
  447         nfsv3err_write,
  448         nfsv3err_create,
  449         nfsv3err_mkdir,
  450         nfsv3err_symlink,
  451         nfsv3err_mknod,
  452         nfsv3err_remove,
  453         nfsv3err_rmdir,
  454         nfsv3err_rename,
  455         nfsv3err_link,
  456         nfsv3err_readdir,
  457         nfsv3err_readdirplus,
  458         nfsv3err_fsstat,
  459         nfsv3err_fsinfo,
  460         nfsv3err_pathconf,
  461         nfsv3err_commit,
  462 };
  463 
  464 /*
  465  * And the same for V4.
  466  */
  467 static short nfsv4err_null[] = {
  468         0,
  469         0,
  470 };
  471 
  472 static short nfsv4err_access[] = {
  473         NFSERR_IO,
  474         NFSERR_ACCES,
  475         NFSERR_BADHANDLE,
  476         NFSERR_BADXDR,
  477         NFSERR_DELAY,
  478         NFSERR_FHEXPIRED,
  479         NFSERR_INVAL,
  480         NFSERR_IO,
  481         NFSERR_MOVED,
  482         NFSERR_NOFILEHANDLE,
  483         NFSERR_RESOURCE,
  484         NFSERR_SERVERFAULT,
  485         NFSERR_STALE,
  486         0,
  487 };
  488 
  489 static short nfsv4err_close[] = {
  490         NFSERR_EXPIRED,
  491         NFSERR_ADMINREVOKED,
  492         NFSERR_BADHANDLE,
  493         NFSERR_BADSEQID,
  494         NFSERR_BADSTATEID,
  495         NFSERR_BADXDR,
  496         NFSERR_DELAY,
  497         NFSERR_EXPIRED,
  498         NFSERR_FHEXPIRED,
  499         NFSERR_INVAL,
  500         NFSERR_ISDIR,
  501         NFSERR_LEASEMOVED,
  502         NFSERR_LOCKSHELD,
  503         NFSERR_MOVED,
  504         NFSERR_NOFILEHANDLE,
  505         NFSERR_OLDSTATEID,
  506         NFSERR_RESOURCE,
  507         NFSERR_SERVERFAULT,
  508         NFSERR_STALE,
  509         NFSERR_STALESTATEID,
  510         0,
  511 };
  512 
  513 static short nfsv4err_commit[] = {
  514         NFSERR_IO,
  515         NFSERR_ACCES,
  516         NFSERR_BADHANDLE,
  517         NFSERR_BADXDR,
  518         NFSERR_FHEXPIRED,
  519         NFSERR_INVAL,
  520         NFSERR_IO,
  521         NFSERR_ISDIR,
  522         NFSERR_MOVED,
  523         NFSERR_NOFILEHANDLE,
  524         NFSERR_RESOURCE,
  525         NFSERR_ROFS,
  526         NFSERR_SERVERFAULT,
  527         NFSERR_STALE,
  528         0,
  529 };
  530 
  531 static short nfsv4err_create[] = {
  532         NFSERR_IO,
  533         NFSERR_ACCES,
  534         NFSERR_ATTRNOTSUPP,
  535         NFSERR_BADCHAR,
  536         NFSERR_BADHANDLE,
  537         NFSERR_BADNAME,
  538         NFSERR_BADOWNER,
  539         NFSERR_BADTYPE,
  540         NFSERR_BADXDR,
  541         NFSERR_DELAY,
  542         NFSERR_DQUOT,
  543         NFSERR_EXIST,
  544         NFSERR_FHEXPIRED,
  545         NFSERR_INVAL,
  546         NFSERR_IO,
  547         NFSERR_MOVED,
  548         NFSERR_NAMETOL,
  549         NFSERR_NOFILEHANDLE,
  550         NFSERR_NOSPC,
  551         NFSERR_NOTDIR,
  552         NFSERR_PERM,
  553         NFSERR_RESOURCE,
  554         NFSERR_ROFS,
  555         NFSERR_SERVERFAULT,
  556         NFSERR_STALE,
  557         0,
  558 };
  559 
  560 static short nfsv4err_delegpurge[] = {
  561         NFSERR_SERVERFAULT,
  562         NFSERR_BADXDR,
  563         NFSERR_NOTSUPP,
  564         NFSERR_LEASEMOVED,
  565         NFSERR_MOVED,
  566         NFSERR_RESOURCE,
  567         NFSERR_SERVERFAULT,
  568         NFSERR_STALECLIENTID,
  569         0,
  570 };
  571 
  572 static short nfsv4err_delegreturn[] = {
  573         NFSERR_SERVERFAULT,
  574         NFSERR_ADMINREVOKED,
  575         NFSERR_BADSTATEID,
  576         NFSERR_BADXDR,
  577         NFSERR_EXPIRED,
  578         NFSERR_INVAL,
  579         NFSERR_LEASEMOVED,
  580         NFSERR_MOVED,
  581         NFSERR_NOFILEHANDLE,
  582         NFSERR_NOTSUPP,
  583         NFSERR_OLDSTATEID,
  584         NFSERR_RESOURCE,
  585         NFSERR_SERVERFAULT,
  586         NFSERR_STALE,
  587         NFSERR_STALESTATEID,
  588         0,
  589 };
  590 
  591 static short nfsv4err_getattr[] = {
  592         NFSERR_IO,
  593         NFSERR_ACCES,
  594         NFSERR_BADHANDLE,
  595         NFSERR_BADXDR,
  596         NFSERR_DELAY,
  597         NFSERR_FHEXPIRED,
  598         NFSERR_INVAL,
  599         NFSERR_IO,
  600         NFSERR_MOVED,
  601         NFSERR_NOFILEHANDLE,
  602         NFSERR_RESOURCE,
  603         NFSERR_SERVERFAULT,
  604         NFSERR_STALE,
  605         0,
  606 };
  607 
  608 static short nfsv4err_getfh[] = {
  609         NFSERR_BADHANDLE,
  610         NFSERR_BADHANDLE,
  611         NFSERR_FHEXPIRED,
  612         NFSERR_MOVED,
  613         NFSERR_NOFILEHANDLE,
  614         NFSERR_RESOURCE,
  615         NFSERR_SERVERFAULT,
  616         NFSERR_STALE,
  617         0,
  618 };
  619 
  620 static short nfsv4err_link[] = {
  621         NFSERR_IO,
  622         NFSERR_ACCES,
  623         NFSERR_BADCHAR,
  624         NFSERR_BADHANDLE,
  625         NFSERR_BADNAME,
  626         NFSERR_BADXDR,
  627         NFSERR_DELAY,
  628         NFSERR_DQUOT,
  629         NFSERR_EXIST,
  630         NFSERR_FHEXPIRED,
  631         NFSERR_FILEOPEN,
  632         NFSERR_INVAL,
  633         NFSERR_IO,
  634         NFSERR_ISDIR,
  635         NFSERR_MLINK,
  636         NFSERR_MOVED,
  637         NFSERR_NAMETOL,
  638         NFSERR_NOENT,
  639         NFSERR_NOFILEHANDLE,
  640         NFSERR_NOSPC,
  641         NFSERR_NOTDIR,
  642         NFSERR_NOTSUPP,
  643         NFSERR_RESOURCE,
  644         NFSERR_ROFS,
  645         NFSERR_SERVERFAULT,
  646         NFSERR_STALE,
  647         NFSERR_WRONGSEC,
  648         NFSERR_XDEV,
  649         0,
  650 };
  651 
  652 static short nfsv4err_lock[] = {
  653         NFSERR_SERVERFAULT,
  654         NFSERR_ACCES,
  655         NFSERR_ADMINREVOKED,
  656         NFSERR_BADHANDLE,
  657         NFSERR_BADRANGE,
  658         NFSERR_BADSEQID,
  659         NFSERR_BADSTATEID,
  660         NFSERR_BADXDR,
  661         NFSERR_DEADLOCK,
  662         NFSERR_DELAY,
  663         NFSERR_DENIED,
  664         NFSERR_EXPIRED,
  665         NFSERR_FHEXPIRED,
  666         NFSERR_GRACE,
  667         NFSERR_INVAL,
  668         NFSERR_ISDIR,
  669         NFSERR_LEASEMOVED,
  670         NFSERR_LOCKNOTSUPP,
  671         NFSERR_LOCKRANGE,
  672         NFSERR_MOVED,
  673         NFSERR_NOFILEHANDLE,
  674         NFSERR_NOGRACE,
  675         NFSERR_OLDSTATEID,
  676         NFSERR_OPENMODE,
  677         NFSERR_RECLAIMBAD,
  678         NFSERR_RECLAIMCONFLICT,
  679         NFSERR_RESOURCE,
  680         NFSERR_SERVERFAULT,
  681         NFSERR_STALE,
  682         NFSERR_STALECLIENTID,
  683         NFSERR_STALESTATEID,
  684         0,
  685 };
  686 
  687 static short nfsv4err_lockt[] = {
  688         NFSERR_SERVERFAULT,
  689         NFSERR_ACCES,
  690         NFSERR_BADHANDLE,
  691         NFSERR_BADRANGE,
  692         NFSERR_BADXDR,
  693         NFSERR_DELAY,
  694         NFSERR_DENIED,
  695         NFSERR_FHEXPIRED,
  696         NFSERR_GRACE,
  697         NFSERR_INVAL,
  698         NFSERR_ISDIR,
  699         NFSERR_LEASEMOVED,
  700         NFSERR_LOCKRANGE,
  701         NFSERR_MOVED,
  702         NFSERR_NOFILEHANDLE,
  703         NFSERR_RESOURCE,
  704         NFSERR_SERVERFAULT,
  705         NFSERR_STALE,
  706         NFSERR_STALECLIENTID,
  707         0,
  708 };
  709 
  710 static short nfsv4err_locku[] = {
  711         NFSERR_SERVERFAULT,
  712         NFSERR_ACCES,
  713         NFSERR_ADMINREVOKED,
  714         NFSERR_BADHANDLE,
  715         NFSERR_BADRANGE,
  716         NFSERR_BADSEQID,
  717         NFSERR_BADSTATEID,
  718         NFSERR_BADXDR,
  719         NFSERR_EXPIRED,
  720         NFSERR_FHEXPIRED,
  721         NFSERR_GRACE,
  722         NFSERR_INVAL,
  723         NFSERR_ISDIR,
  724         NFSERR_LEASEMOVED,
  725         NFSERR_LOCKRANGE,
  726         NFSERR_MOVED,
  727         NFSERR_NOFILEHANDLE,
  728         NFSERR_OLDSTATEID,
  729         NFSERR_RESOURCE,
  730         NFSERR_SERVERFAULT,
  731         NFSERR_STALE,
  732         NFSERR_STALESTATEID,
  733         0,
  734 };
  735 
  736 static short nfsv4err_lookup[] = {
  737         NFSERR_IO,
  738         NFSERR_ACCES,
  739         NFSERR_BADCHAR,
  740         NFSERR_BADHANDLE,
  741         NFSERR_BADNAME,
  742         NFSERR_BADXDR,
  743         NFSERR_FHEXPIRED,
  744         NFSERR_INVAL,
  745         NFSERR_IO,
  746         NFSERR_MOVED,
  747         NFSERR_NAMETOL,
  748         NFSERR_NOENT,
  749         NFSERR_NOFILEHANDLE,
  750         NFSERR_NOTDIR,
  751         NFSERR_RESOURCE,
  752         NFSERR_SERVERFAULT,
  753         NFSERR_STALE,
  754         NFSERR_SYMLINK,
  755         NFSERR_WRONGSEC,
  756         0,
  757 };
  758 
  759 static short nfsv4err_lookupp[] = {
  760         NFSERR_IO,
  761         NFSERR_ACCES,
  762         NFSERR_BADHANDLE,
  763         NFSERR_FHEXPIRED,
  764         NFSERR_IO,
  765         NFSERR_MOVED,
  766         NFSERR_NOENT,
  767         NFSERR_NOFILEHANDLE,
  768         NFSERR_NOTDIR,
  769         NFSERR_RESOURCE,
  770         NFSERR_SERVERFAULT,
  771         NFSERR_STALE,
  772         0,
  773 };
  774 
  775 static short nfsv4err_nverify[] = {
  776         NFSERR_IO,
  777         NFSERR_ACCES,
  778         NFSERR_ATTRNOTSUPP,
  779         NFSERR_BADCHAR,
  780         NFSERR_BADHANDLE,
  781         NFSERR_BADXDR,
  782         NFSERR_DELAY,
  783         NFSERR_FHEXPIRED,
  784         NFSERR_INVAL,
  785         NFSERR_IO,
  786         NFSERR_MOVED,
  787         NFSERR_NOFILEHANDLE,
  788         NFSERR_RESOURCE,
  789         NFSERR_SAME,
  790         NFSERR_SERVERFAULT,
  791         NFSERR_STALE,
  792         0,
  793 };
  794 
  795 static short nfsv4err_open[] = {
  796         NFSERR_IO,
  797         NFSERR_ACCES,
  798         NFSERR_ADMINREVOKED,
  799         NFSERR_ATTRNOTSUPP,
  800         NFSERR_BADCHAR,
  801         NFSERR_BADHANDLE,
  802         NFSERR_BADNAME,
  803         NFSERR_BADOWNER,
  804         NFSERR_BADSEQID,
  805         NFSERR_BADXDR,
  806         NFSERR_DELAY,
  807         NFSERR_DQUOT,
  808         NFSERR_EXIST,
  809         NFSERR_EXPIRED,
  810         NFSERR_FHEXPIRED,
  811         NFSERR_GRACE,
  812         NFSERR_IO,
  813         NFSERR_INVAL,
  814         NFSERR_ISDIR,
  815         NFSERR_LEASEMOVED,
  816         NFSERR_MOVED,
  817         NFSERR_NAMETOL,
  818         NFSERR_NOENT,
  819         NFSERR_NOFILEHANDLE,
  820         NFSERR_NOGRACE,
  821         NFSERR_NOSPC,
  822         NFSERR_NOTDIR,
  823         NFSERR_NOTSUPP,
  824         NFSERR_PERM,
  825         NFSERR_RECLAIMBAD,
  826         NFSERR_RECLAIMCONFLICT,
  827         NFSERR_RESOURCE,
  828         NFSERR_ROFS,
  829         NFSERR_SERVERFAULT,
  830         NFSERR_SHAREDENIED,
  831         NFSERR_STALE,
  832         NFSERR_STALECLIENTID,
  833         NFSERR_SYMLINK,
  834         NFSERR_WRONGSEC,
  835         0,
  836 };
  837 
  838 static short nfsv4err_openattr[] = {
  839         NFSERR_IO,
  840         NFSERR_ACCES,
  841         NFSERR_BADHANDLE,
  842         NFSERR_BADXDR,
  843         NFSERR_DELAY,
  844         NFSERR_DQUOT,
  845         NFSERR_FHEXPIRED,
  846         NFSERR_IO,
  847         NFSERR_MOVED,
  848         NFSERR_NOENT,
  849         NFSERR_NOFILEHANDLE,
  850         NFSERR_NOSPC,
  851         NFSERR_NOTSUPP,
  852         NFSERR_RESOURCE,
  853         NFSERR_ROFS,
  854         NFSERR_SERVERFAULT,
  855         NFSERR_STALE,
  856         0,
  857 };
  858 
  859 static short nfsv4err_openconfirm[] = {
  860         NFSERR_SERVERFAULT,
  861         NFSERR_ADMINREVOKED,
  862         NFSERR_BADHANDLE,
  863         NFSERR_BADSEQID,
  864         NFSERR_BADSTATEID,
  865         NFSERR_BADXDR,
  866         NFSERR_EXPIRED,
  867         NFSERR_FHEXPIRED,
  868         NFSERR_INVAL,
  869         NFSERR_ISDIR,
  870         NFSERR_MOVED,
  871         NFSERR_NOFILEHANDLE,
  872         NFSERR_OLDSTATEID,
  873         NFSERR_RESOURCE,
  874         NFSERR_SERVERFAULT,
  875         NFSERR_STALE,
  876         NFSERR_STALESTATEID,
  877         0,
  878 };
  879 
  880 static short nfsv4err_opendowngrade[] = {
  881         NFSERR_SERVERFAULT,
  882         NFSERR_ADMINREVOKED,
  883         NFSERR_BADHANDLE,
  884         NFSERR_BADSEQID,
  885         NFSERR_BADSTATEID,
  886         NFSERR_BADXDR,
  887         NFSERR_EXPIRED,
  888         NFSERR_FHEXPIRED,
  889         NFSERR_INVAL,
  890         NFSERR_MOVED,
  891         NFSERR_NOFILEHANDLE,
  892         NFSERR_OLDSTATEID,
  893         NFSERR_RESOURCE,
  894         NFSERR_SERVERFAULT,
  895         NFSERR_STALE,
  896         NFSERR_STALESTATEID,
  897         0,
  898 };
  899 
  900 static short nfsv4err_putfh[] = {
  901         NFSERR_SERVERFAULT,
  902         NFSERR_BADHANDLE,
  903         NFSERR_BADXDR,
  904         NFSERR_FHEXPIRED,
  905         NFSERR_MOVED,
  906         NFSERR_RESOURCE,
  907         NFSERR_SERVERFAULT,
  908         NFSERR_STALE,
  909         NFSERR_WRONGSEC,
  910         0,
  911 };
  912 
  913 static short nfsv4err_putpubfh[] = {
  914         NFSERR_SERVERFAULT,
  915         NFSERR_RESOURCE,
  916         NFSERR_SERVERFAULT,
  917         NFSERR_WRONGSEC,
  918         0,
  919 };
  920 
  921 static short nfsv4err_putrootfh[] = {
  922         NFSERR_SERVERFAULT,
  923         NFSERR_RESOURCE,
  924         NFSERR_SERVERFAULT,
  925         NFSERR_WRONGSEC,
  926         0,
  927 };
  928 
  929 static short nfsv4err_read[] = {
  930         NFSERR_IO,
  931         NFSERR_ACCES,
  932         NFSERR_ADMINREVOKED,
  933         NFSERR_BADHANDLE,
  934         NFSERR_BADSTATEID,
  935         NFSERR_BADXDR,
  936         NFSERR_DELAY,
  937         NFSERR_EXPIRED,
  938         NFSERR_FHEXPIRED,
  939         NFSERR_GRACE,
  940         NFSERR_IO,
  941         NFSERR_INVAL,
  942         NFSERR_ISDIR,
  943         NFSERR_LEASEMOVED,
  944         NFSERR_LOCKED,
  945         NFSERR_MOVED,
  946         NFSERR_NOFILEHANDLE,
  947         NFSERR_NXIO,
  948         NFSERR_OLDSTATEID,
  949         NFSERR_OPENMODE,
  950         NFSERR_RESOURCE,
  951         NFSERR_SERVERFAULT,
  952         NFSERR_STALE,
  953         NFSERR_STALESTATEID,
  954         0,
  955 };
  956 
  957 static short nfsv4err_readdir[] = {
  958         NFSERR_IO,
  959         NFSERR_ACCES,
  960         NFSERR_BADHANDLE,
  961         NFSERR_BAD_COOKIE,
  962         NFSERR_BADXDR,
  963         NFSERR_DELAY,
  964         NFSERR_FHEXPIRED,
  965         NFSERR_INVAL,
  966         NFSERR_IO,
  967         NFSERR_MOVED,
  968         NFSERR_NOFILEHANDLE,
  969         NFSERR_NOTDIR,
  970         NFSERR_NOTSAME,
  971         NFSERR_RESOURCE,
  972         NFSERR_SERVERFAULT,
  973         NFSERR_STALE,
  974         NFSERR_TOOSMALL,
  975         0,
  976 };
  977 
  978 static short nfsv4err_readlink[] = {
  979         NFSERR_IO,
  980         NFSERR_ACCES,
  981         NFSERR_BADHANDLE,
  982         NFSERR_DELAY,
  983         NFSERR_FHEXPIRED,
  984         NFSERR_INVAL,
  985         NFSERR_IO,
  986         NFSERR_ISDIR,
  987         NFSERR_MOVED,
  988         NFSERR_NOFILEHANDLE,
  989         NFSERR_NOTSUPP,
  990         NFSERR_RESOURCE,
  991         NFSERR_SERVERFAULT,
  992         NFSERR_STALE,
  993         0,
  994 };
  995 
  996 static short nfsv4err_remove[] = {
  997         NFSERR_IO,
  998         NFSERR_ACCES,
  999         NFSERR_BADCHAR,
 1000         NFSERR_BADHANDLE,
 1001         NFSERR_BADNAME,
 1002         NFSERR_BADXDR,
 1003         NFSERR_DELAY,
 1004         NFSERR_FHEXPIRED,
 1005         NFSERR_FILEOPEN,
 1006         NFSERR_INVAL,
 1007         NFSERR_IO,
 1008         NFSERR_MOVED,
 1009         NFSERR_NAMETOL,
 1010         NFSERR_NOENT,
 1011         NFSERR_NOFILEHANDLE,
 1012         NFSERR_NOTDIR,
 1013         NFSERR_NOTEMPTY,
 1014         NFSERR_RESOURCE,
 1015         NFSERR_ROFS,
 1016         NFSERR_SERVERFAULT,
 1017         NFSERR_STALE,
 1018         0,
 1019 };
 1020 
 1021 static short nfsv4err_rename[] = {
 1022         NFSERR_IO,
 1023         NFSERR_ACCES,
 1024         NFSERR_BADCHAR,
 1025         NFSERR_BADHANDLE,
 1026         NFSERR_BADNAME,
 1027         NFSERR_BADXDR,
 1028         NFSERR_DELAY,
 1029         NFSERR_DQUOT,
 1030         NFSERR_EXIST,
 1031         NFSERR_FHEXPIRED,
 1032         NFSERR_FILEOPEN,
 1033         NFSERR_INVAL,
 1034         NFSERR_IO,
 1035         NFSERR_MOVED,
 1036         NFSERR_NAMETOL,
 1037         NFSERR_NOENT,
 1038         NFSERR_NOFILEHANDLE,
 1039         NFSERR_NOSPC,
 1040         NFSERR_NOTDIR,
 1041         NFSERR_NOTEMPTY,
 1042         NFSERR_RESOURCE,
 1043         NFSERR_ROFS,
 1044         NFSERR_SERVERFAULT,
 1045         NFSERR_STALE,
 1046         NFSERR_WRONGSEC,
 1047         NFSERR_XDEV,
 1048         0,
 1049 };
 1050 
 1051 static short nfsv4err_renew[] = {
 1052         NFSERR_SERVERFAULT,
 1053         NFSERR_ACCES,
 1054         NFSERR_ADMINREVOKED,
 1055         NFSERR_BADXDR,
 1056         NFSERR_CBPATHDOWN,
 1057         NFSERR_EXPIRED,
 1058         NFSERR_LEASEMOVED,
 1059         NFSERR_RESOURCE,
 1060         NFSERR_SERVERFAULT,
 1061         NFSERR_STALECLIENTID,
 1062         0,
 1063 };
 1064 
 1065 static short nfsv4err_restorefh[] = {
 1066         NFSERR_SERVERFAULT,
 1067         NFSERR_BADHANDLE,
 1068         NFSERR_FHEXPIRED,
 1069         NFSERR_MOVED,
 1070         NFSERR_RESOURCE,
 1071         NFSERR_RESTOREFH,
 1072         NFSERR_SERVERFAULT,
 1073         NFSERR_STALE,
 1074         NFSERR_WRONGSEC,
 1075         0,
 1076 };
 1077 
 1078 static short nfsv4err_savefh[] = {
 1079         NFSERR_SERVERFAULT,
 1080         NFSERR_BADHANDLE,
 1081         NFSERR_FHEXPIRED,
 1082         NFSERR_MOVED,
 1083         NFSERR_NOFILEHANDLE,
 1084         NFSERR_RESOURCE,
 1085         NFSERR_SERVERFAULT,
 1086         NFSERR_STALE,
 1087         0,
 1088 };
 1089 
 1090 static short nfsv4err_secinfo[] = {
 1091         NFSERR_SERVERFAULT,
 1092         NFSERR_ACCES,
 1093         NFSERR_BADCHAR,
 1094         NFSERR_BADHANDLE,
 1095         NFSERR_BADNAME,
 1096         NFSERR_BADXDR,
 1097         NFSERR_FHEXPIRED,
 1098         NFSERR_INVAL,
 1099         NFSERR_MOVED,
 1100         NFSERR_NAMETOL,
 1101         NFSERR_NOENT,
 1102         NFSERR_NOFILEHANDLE,
 1103         NFSERR_NOTDIR,
 1104         NFSERR_RESOURCE,
 1105         NFSERR_SERVERFAULT,
 1106         NFSERR_STALE,
 1107         0,
 1108 };
 1109 
 1110 static short nfsv4err_setattr[] = {
 1111         NFSERR_IO,
 1112         NFSERR_ACCES,
 1113         NFSERR_ADMINREVOKED,
 1114         NFSERR_ATTRNOTSUPP,
 1115         NFSERR_BADCHAR,
 1116         NFSERR_BADHANDLE,
 1117         NFSERR_BADOWNER,
 1118         NFSERR_BADSTATEID,
 1119         NFSERR_BADXDR,
 1120         NFSERR_DELAY,
 1121         NFSERR_DQUOT,
 1122         NFSERR_EXPIRED,
 1123         NFSERR_FBIG,
 1124         NFSERR_FHEXPIRED,
 1125         NFSERR_GRACE,
 1126         NFSERR_INVAL,
 1127         NFSERR_IO,
 1128         NFSERR_ISDIR,
 1129         NFSERR_LOCKED,
 1130         NFSERR_MOVED,
 1131         NFSERR_NOFILEHANDLE,
 1132         NFSERR_NOSPC,
 1133         NFSERR_OLDSTATEID,
 1134         NFSERR_OPENMODE,
 1135         NFSERR_PERM,
 1136         NFSERR_RESOURCE,
 1137         NFSERR_ROFS,
 1138         NFSERR_SERVERFAULT,
 1139         NFSERR_STALE,
 1140         NFSERR_STALESTATEID,
 1141         0,
 1142 };
 1143 
 1144 static short nfsv4err_setclientid[] = {
 1145         NFSERR_SERVERFAULT,
 1146         NFSERR_BADXDR,
 1147         NFSERR_CLIDINUSE,
 1148         NFSERR_INVAL,
 1149         NFSERR_RESOURCE,
 1150         NFSERR_SERVERFAULT,
 1151         NFSERR_WRONGSEC,
 1152         0,
 1153 };
 1154 
 1155 static short nfsv4err_setclientidconfirm[] = {
 1156         NFSERR_SERVERFAULT,
 1157         NFSERR_BADXDR,
 1158         NFSERR_CLIDINUSE,
 1159         NFSERR_RESOURCE,
 1160         NFSERR_SERVERFAULT,
 1161         NFSERR_STALECLIENTID,
 1162         0,
 1163 };
 1164 
 1165 static short nfsv4err_verify[] = {
 1166         NFSERR_SERVERFAULT,
 1167         NFSERR_ACCES,
 1168         NFSERR_ATTRNOTSUPP,
 1169         NFSERR_BADCHAR,
 1170         NFSERR_BADHANDLE,
 1171         NFSERR_BADXDR,
 1172         NFSERR_DELAY,
 1173         NFSERR_FHEXPIRED,
 1174         NFSERR_INVAL,
 1175         NFSERR_MOVED,
 1176         NFSERR_NOFILEHANDLE,
 1177         NFSERR_NOTSAME,
 1178         NFSERR_RESOURCE,
 1179         NFSERR_SERVERFAULT,
 1180         NFSERR_STALE,
 1181         0,
 1182 };
 1183 
 1184 static short nfsv4err_write[] = {
 1185         NFSERR_IO,
 1186         NFSERR_ACCES,
 1187         NFSERR_ADMINREVOKED,
 1188         NFSERR_BADHANDLE,
 1189         NFSERR_BADSTATEID,
 1190         NFSERR_BADXDR,
 1191         NFSERR_DELAY,
 1192         NFSERR_DQUOT,
 1193         NFSERR_EXPIRED,
 1194         NFSERR_FBIG,
 1195         NFSERR_FHEXPIRED,
 1196         NFSERR_GRACE,
 1197         NFSERR_INVAL,
 1198         NFSERR_IO,
 1199         NFSERR_ISDIR,
 1200         NFSERR_LEASEMOVED,
 1201         NFSERR_LOCKED,
 1202         NFSERR_MOVED,
 1203         NFSERR_NOFILEHANDLE,
 1204         NFSERR_NOSPC,
 1205         NFSERR_NXIO,
 1206         NFSERR_OLDSTATEID,
 1207         NFSERR_OPENMODE,
 1208         NFSERR_RESOURCE,
 1209         NFSERR_ROFS,
 1210         NFSERR_SERVERFAULT,
 1211         NFSERR_STALE,
 1212         NFSERR_STALESTATEID,
 1213         0,
 1214 };
 1215 
 1216 static short nfsv4err_releaselockowner[] = {
 1217         NFSERR_SERVERFAULT,
 1218         NFSERR_ADMINREVOKED,
 1219         NFSERR_BADXDR,
 1220         NFSERR_EXPIRED,
 1221         NFSERR_LEASEMOVED,
 1222         NFSERR_LOCKSHELD,
 1223         NFSERR_RESOURCE,
 1224         NFSERR_SERVERFAULT,
 1225         NFSERR_STALECLIENTID,
 1226         0,
 1227 };
 1228 
 1229 static short *nfsrv_v4errmap[] = {
 1230         nfsv4err_null,
 1231         nfsv4err_null,
 1232         nfsv4err_null,
 1233         nfsv4err_access,
 1234         nfsv4err_close,
 1235         nfsv4err_commit,
 1236         nfsv4err_create,
 1237         nfsv4err_delegpurge,
 1238         nfsv4err_delegreturn,
 1239         nfsv4err_getattr,
 1240         nfsv4err_getfh,
 1241         nfsv4err_link,
 1242         nfsv4err_lock,
 1243         nfsv4err_lockt,
 1244         nfsv4err_locku,
 1245         nfsv4err_lookup,
 1246         nfsv4err_lookupp,
 1247         nfsv4err_nverify,
 1248         nfsv4err_open,
 1249         nfsv4err_openattr,
 1250         nfsv4err_openconfirm,
 1251         nfsv4err_opendowngrade,
 1252         nfsv4err_putfh,
 1253         nfsv4err_putpubfh,
 1254         nfsv4err_putrootfh,
 1255         nfsv4err_read,
 1256         nfsv4err_readdir,
 1257         nfsv4err_readlink,
 1258         nfsv4err_remove,
 1259         nfsv4err_rename,
 1260         nfsv4err_renew,
 1261         nfsv4err_restorefh,
 1262         nfsv4err_savefh,
 1263         nfsv4err_secinfo,
 1264         nfsv4err_setattr,
 1265         nfsv4err_setclientid,
 1266         nfsv4err_setclientidconfirm,
 1267         nfsv4err_verify,
 1268         nfsv4err_write,
 1269         nfsv4err_releaselockowner,
 1270 };
 1271 
 1272 /*
 1273  * A fiddled version of m_adj() that ensures null fill to a long
 1274  * boundary and only trims off the back end
 1275  */
 1276 APPLESTATIC void
 1277 nfsrv_adj(mbuf_t mp, int len, int nul)
 1278 {
 1279         mbuf_t m;
 1280         int count, i;
 1281         char *cp;
 1282 
 1283         /*
 1284          * Trim from tail.  Scan the mbuf chain,
 1285          * calculating its length and finding the last mbuf.
 1286          * If the adjustment only affects this mbuf, then just
 1287          * adjust and return.  Otherwise, rescan and truncate
 1288          * after the remaining size.
 1289          */
 1290         count = 0;
 1291         m = mp;
 1292         for (;;) {
 1293                 count += mbuf_len(m);
 1294                 if (mbuf_next(m) == NULL)
 1295                         break;
 1296                 m = mbuf_next(m);
 1297         }
 1298         if (mbuf_len(m) > len) {
 1299                 mbuf_setlen(m, mbuf_len(m) - len);
 1300                 if (nul > 0) {
 1301                         cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
 1302                         for (i = 0; i < nul; i++)
 1303                                 *cp++ = '\0';
 1304                 }
 1305                 return;
 1306         }
 1307         count -= len;
 1308         if (count < 0)
 1309                 count = 0;
 1310         /*
 1311          * Correct length for chain is "count".
 1312          * Find the mbuf with last data, adjust its length,
 1313          * and toss data from remaining mbufs on chain.
 1314          */
 1315         for (m = mp; m; m = mbuf_next(m)) {
 1316                 if (mbuf_len(m) >= count) {
 1317                         mbuf_setlen(m, count);
 1318                         if (nul > 0) {
 1319                                 cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
 1320                                 for (i = 0; i < nul; i++)
 1321                                         *cp++ = '\0';
 1322                         }
 1323                         break;
 1324                 }
 1325                 count -= mbuf_len(m);
 1326         }
 1327         for (m = mbuf_next(m); m; m = mbuf_next(m))
 1328                 mbuf_setlen(m, 0);
 1329 }
 1330 
 1331 /*
 1332  * Make these functions instead of macros, so that the kernel text size
 1333  * doesn't get too big...
 1334  */
 1335 APPLESTATIC void
 1336 nfsrv_wcc(struct nfsrv_descript *nd, int before_ret,
 1337     struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap)
 1338 {
 1339         u_int32_t *tl;
 1340 
 1341         if (before_ret) {
 1342                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1343                 *tl = newnfs_false;
 1344         } else {
 1345                 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 1346                 *tl++ = newnfs_true;
 1347                 txdr_hyper(before_nvap->na_size, tl);
 1348                 tl += 2;
 1349                 txdr_nfsv3time(&(before_nvap->na_mtime), tl);
 1350                 tl += 2;
 1351                 txdr_nfsv3time(&(before_nvap->na_ctime), tl);
 1352         }
 1353         nfsrv_postopattr(nd, after_ret, after_nvap);
 1354 }
 1355 
 1356 APPLESTATIC void
 1357 nfsrv_postopattr(struct nfsrv_descript *nd, int after_ret,
 1358     struct nfsvattr *after_nvap)
 1359 {
 1360         u_int32_t *tl;
 1361 
 1362         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1363         if (after_ret)
 1364                 *tl = newnfs_false;
 1365         else {
 1366                 *tl = newnfs_true;
 1367                 nfsrv_fillattr(nd, after_nvap);
 1368         }
 1369 }
 1370 
 1371 /*
 1372  * Fill in file attributes for V2 and 3. For V4, call a separate
 1373  * routine that sifts through all the attribute bits.
 1374  */
 1375 APPLESTATIC void
 1376 nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap)
 1377 {
 1378         struct nfs_fattr *fp;
 1379         int fattr_size;
 1380 
 1381         /*
 1382          * Build space for the attribute structure.
 1383          */
 1384         if (nd->nd_flag & ND_NFSV3)
 1385                 fattr_size = NFSX_V3FATTR;
 1386         else
 1387                 fattr_size = NFSX_V2FATTR;
 1388         NFSM_BUILD(fp, struct nfs_fattr *, fattr_size);
 1389 
 1390         /*
 1391          * Now just fill it all in.
 1392          */
 1393         fp->fa_nlink = txdr_unsigned(nvap->na_nlink);
 1394         fp->fa_uid = txdr_unsigned(nvap->na_uid);
 1395         fp->fa_gid = txdr_unsigned(nvap->na_gid);
 1396         if (nd->nd_flag & ND_NFSV3) {
 1397                 fp->fa_type = vtonfsv34_type(nvap->na_type);
 1398                 fp->fa_mode = vtonfsv34_mode(nvap->na_mode);
 1399                 txdr_hyper(nvap->na_size, &fp->fa3_size);
 1400                 txdr_hyper(nvap->na_bytes, &fp->fa3_used);
 1401                 fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev));
 1402                 fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev));
 1403                 fp->fa3_fsid.nfsuquad[0] = 0;
 1404                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid);
 1405                 txdr_hyper(nvap->na_fileid, &fp->fa3_fileid);
 1406                 txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime);
 1407                 txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime);
 1408                 txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime);
 1409         } else {
 1410                 fp->fa_type = vtonfsv2_type(nvap->na_type);
 1411                 fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode);
 1412                 fp->fa2_size = txdr_unsigned(nvap->na_size);
 1413                 fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize);
 1414                 if (nvap->na_type == VFIFO)
 1415                         fp->fa2_rdev = 0xffffffff;
 1416                 else
 1417                         fp->fa2_rdev = txdr_unsigned(nvap->na_rdev);
 1418                 fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE);
 1419                 fp->fa2_fsid = txdr_unsigned(nvap->na_fsid);
 1420                 fp->fa2_fileid = txdr_unsigned(nvap->na_fileid);
 1421                 txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime);
 1422                 txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime);
 1423                 txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime);
 1424         }
 1425 }
 1426 
 1427 /*
 1428  * This function gets a file handle out of an mbuf list.
 1429  * It returns 0 for success, EBADRPC otherwise.
 1430  * If sets the third flagp argument to 1 if the file handle is
 1431  * the public file handle.
 1432  * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE
 1433  */
 1434 APPLESTATIC int
 1435 nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
 1436 {
 1437         u_int32_t *tl;
 1438         int error = 0, len, copylen;
 1439 
 1440         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1441                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1442                 len = fxdr_unsigned(int, *tl);
 1443                 if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) &&
 1444                     nd->nd_procnum == NFSPROC_LOOKUP) {
 1445                         nd->nd_flag |= ND_PUBLOOKUP;
 1446                         goto nfsmout;
 1447                 }
 1448                 copylen = len;
 1449 
 1450                 /* If len == NFSX_V4PNFSFH the RPC is a pNFS DS one. */
 1451                 if (len == NFSX_V4PNFSFH && (nd->nd_flag & ND_NFSV41) != 0) {
 1452                         copylen = NFSX_MYFH;
 1453                         len = NFSM_RNDUP(len);
 1454                         nd->nd_flag |= ND_DSSERVER;
 1455                 } else if (len < NFSRV_MINFH || len > NFSRV_MAXFH) {
 1456                         if (nd->nd_flag & ND_NFSV4) {
 1457                             if (len > 0 && len <= NFSX_V4FHMAX) {
 1458                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 1459                                 if (error)
 1460                                         goto nfsmout;
 1461                                 nd->nd_repstat = NFSERR_BADHANDLE;
 1462                                 goto nfsmout;
 1463                             } else {
 1464                                     error = EBADRPC;
 1465                                     goto nfsmout;
 1466                             }
 1467                         } else {
 1468                                 error = EBADRPC;
 1469                                 goto nfsmout;
 1470                         }
 1471                 }
 1472         } else {
 1473                 /*
 1474                  * For NFSv2, the file handle is always 32 bytes on the
 1475                  * wire, but this server only cares about the first
 1476                  * NFSRV_MAXFH bytes.
 1477                  */
 1478                 len = NFSX_V2FH;
 1479                 copylen = NFSRV_MAXFH;
 1480         }
 1481         NFSM_DISSECT(tl, u_int32_t *, len);
 1482         if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset &&
 1483             nd->nd_procnum == NFSPROC_LOOKUP &&
 1484             !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) {
 1485                 nd->nd_flag |= ND_PUBLOOKUP;
 1486                 goto nfsmout;
 1487         }
 1488         NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen);
 1489         fhp->nfsrvfh_len = copylen;
 1490 nfsmout:
 1491         NFSEXITCODE2(error, nd);
 1492         return (error);
 1493 }
 1494 
 1495 /*
 1496  * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error
 1497  * numbers not specified for the associated procedure.
 1498  * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat
 1499  * should be cleared. NFSPROC_NOOP is used to return errors when a valid
 1500  * RPC procedure is not involved.
 1501  * Returns the error number in XDR.
 1502  */
 1503 APPLESTATIC int
 1504 nfsd_errmap(struct nfsrv_descript *nd)
 1505 {
 1506         short *defaulterrp, *errp;
 1507 
 1508         if (!nd->nd_repstat)
 1509                 return (0);
 1510         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1511                 if (nd->nd_procnum == NFSPROC_NOOP)
 1512                         return (txdr_unsigned(nd->nd_repstat & 0xffff));
 1513                 if (nd->nd_flag & ND_NFSV3)
 1514                     errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
 1515                 else if (nd->nd_repstat == EBADRPC)
 1516                         return (txdr_unsigned(NFSERR_BADXDR));
 1517                 else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH ||
 1518                          nd->nd_repstat == NFSERR_OPILLEGAL)
 1519                         return (txdr_unsigned(nd->nd_repstat));
 1520                 else if ((nd->nd_flag & ND_NFSV41) != 0) {
 1521                         if (nd->nd_repstat == EOPNOTSUPP)
 1522                                 nd->nd_repstat = NFSERR_NOTSUPP;
 1523                         nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat);
 1524                         return (txdr_unsigned(nd->nd_repstat));
 1525                 } else
 1526                     errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum];
 1527                 while (*++errp)
 1528                         if (*errp == nd->nd_repstat)
 1529                                 return (txdr_unsigned(nd->nd_repstat));
 1530                 return (txdr_unsigned(*defaulterrp));
 1531         }
 1532         if (nd->nd_repstat <= NFSERR_REMOTE)
 1533                 return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1]));
 1534         return (txdr_unsigned(NFSERR_IO));
 1535 }
 1536 
 1537 /*
 1538  * Check to see if the error is a valid NFS one. If not, replace it with
 1539  * NFSERR_IO.
 1540  */
 1541 static u_int32_t
 1542 nfsrv_isannfserr(u_int32_t errval)
 1543 {
 1544 
 1545         if (errval == NFSERR_OK)
 1546                 return (errval);
 1547         if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_DELEGREVOKED)
 1548                 return (errval);
 1549         if (errval > 0 && errval <= NFSERR_REMOTE)
 1550                 return (nfsrv_v2errmap[errval - 1]);
 1551         return (NFSERR_IO);
 1552 }
 1553 
 1554 /*
 1555  * Check to see if setting a uid/gid is permitted when creating a new
 1556  * file object. (Called when uid and/or gid is specified in the
 1557  * settable attributes for V4.
 1558  */
 1559 APPLESTATIC int
 1560 nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap)
 1561 {
 1562         int error = 0;
 1563 
 1564         /*
 1565          * If not setting either uid nor gid, it's OK.
 1566          */
 1567         if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap))
 1568                 goto out;
 1569         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid &&
 1570            enable_nobodycheck == 1)
 1571             || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid &&
 1572            enable_nogroupcheck == 1)) {
 1573                 error = NFSERR_BADOWNER;
 1574                 goto out;
 1575         }
 1576         if (nd->nd_cred->cr_uid == 0)
 1577                 goto out;
 1578         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) ||
 1579             (NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid &&
 1580             !groupmember(nvap->na_gid, nd->nd_cred)))
 1581                 error = NFSERR_PERM;
 1582 
 1583 out:
 1584         NFSEXITCODE2(error, nd);
 1585         return (error);
 1586 }
 1587 
 1588 /*
 1589  * and this routine fixes up the settable attributes for V4 if allowed
 1590  * by nfsrv_checkuidgid().
 1591  */
 1592 APPLESTATIC void
 1593 nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
 1594     struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp,
 1595     struct nfsexstuff *exp)
 1596 {
 1597         int change = 0;
 1598         struct nfsvattr nva;
 1599         uid_t tuid;
 1600         int error;
 1601         nfsattrbit_t nattrbits;
 1602 
 1603         /*
 1604          * Maybe this should be done for V2 and 3 but it never has been
 1605          * and nobody seems to be upset, so I think it's best not to change
 1606          * the V2 and 3 semantics.
 1607          */
 1608         if ((nd->nd_flag & ND_NFSV4) == 0)
 1609                 goto out;
 1610         NFSVNO_ATTRINIT(&nva);
 1611         NFSZERO_ATTRBIT(&nattrbits);
 1612         tuid = nd->nd_cred->cr_uid;
 1613         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) &&
 1614             NFSVNO_ISSETUID(nvap) &&
 1615             nvap->na_uid != nd->nd_cred->cr_uid) {
 1616                 if (nd->nd_cred->cr_uid == 0) {
 1617                         nva.na_uid = nvap->na_uid;
 1618                         change++;
 1619                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER);
 1620                 } else {
 1621                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER);
 1622                 }
 1623         }
 1624         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) &&
 1625             NFSVNO_ISSETATIME(nvap)) {
 1626                 nva.na_atime = nvap->na_atime;
 1627                 change++;
 1628                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET);
 1629         }
 1630         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) &&
 1631             NFSVNO_ISSETMTIME(nvap)) {
 1632                 nva.na_mtime = nvap->na_mtime;
 1633                 change++;
 1634                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET);
 1635         }
 1636         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) &&
 1637             NFSVNO_ISSETGID(nvap)) {
 1638                 if (nvap->na_gid == nd->nd_cred->cr_gid ||
 1639                     groupmember(nvap->na_gid, nd->nd_cred)) {
 1640                         nd->nd_cred->cr_uid = 0;
 1641                         nva.na_gid = nvap->na_gid;
 1642                         change++;
 1643                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP);
 1644                 } else {
 1645                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
 1646                 }
 1647         }
 1648         if (change) {
 1649                 error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
 1650                 if (error) {
 1651                         NFSCLRALL_ATTRBIT(attrbitp, &nattrbits);
 1652                 }
 1653         }
 1654         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) &&
 1655             NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) {
 1656                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE);
 1657         }
 1658 #ifdef NFS4_ACL_EXTATTR_NAME
 1659         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) &&
 1660             nfsrv_useacl != 0 && aclp != NULL) {
 1661                 if (aclp->acl_cnt > 0) {
 1662                         error = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
 1663                         if (error) {
 1664                                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
 1665                         }
 1666                 }
 1667         } else
 1668 #endif
 1669         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
 1670         nd->nd_cred->cr_uid = tuid;
 1671 
 1672 out:
 1673         NFSEXITCODE2(0, nd);
 1674 }
 1675 
 1676 /*
 1677  * Translate an ASCII hex digit to it's binary value. Return -1 if the
 1678  * char isn't a hex digit.
 1679  */
 1680 static char
 1681 nfsrv_hexdigit(char c, int *err)
 1682 {
 1683 
 1684         *err = 0;
 1685         if (c >= '' && c <= '9')
 1686                 return (c - '');
 1687         if (c >= 'a' && c <= 'f')
 1688                 return (c - 'a' + ((char)10));
 1689         if (c >= 'A' && c <= 'F')
 1690                 return (c - 'A' + ((char)10));
 1691         /* Not valid ! */
 1692         *err = 1;
 1693         return (1);     /* BOGUS */
 1694 }
 1695 
 1696 /*
 1697  * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff
 1698  * it can be.
 1699  */
 1700 APPLESTATIC int
 1701 nfsrv_errmoved(int op)
 1702 {
 1703         short *errp;
 1704 
 1705         errp = nfsrv_v4errmap[op];
 1706         while (*errp != 0) {
 1707                 if (*errp == NFSERR_MOVED)
 1708                         return (1);
 1709                 errp++;
 1710         }
 1711         return (0);
 1712 }
 1713 
 1714 /*
 1715  * Fill in attributes for a Referral.
 1716  * (Return the number of bytes of XDR created.)
 1717  */
 1718 APPLESTATIC int
 1719 nfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp,
 1720     struct nfsreferral *refp, int getattr, int *reterrp)
 1721 {
 1722         u_int32_t *tl, *retnump;
 1723         u_char *cp, *cp2;
 1724         int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0;
 1725         int fslocationsbit = 0;
 1726         nfsattrbit_t tmpbits, refbits;
 1727 
 1728         NFSREFERRAL_ATTRBIT(&refbits);
 1729         if (getattr)
 1730                 NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR);
 1731         else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR))
 1732                 rderrbit = 1;
 1733         if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS))
 1734                 fslocationsbit = 1;
 1735 
 1736         /*
 1737          * Check for the case where unsupported referral attributes are
 1738          * requested.
 1739          */
 1740         NFSSET_ATTRBIT(&tmpbits, retbitp);
 1741         NFSCLRALL_ATTRBIT(&tmpbits, &refbits);
 1742         if (NFSNONZERO_ATTRBIT(&tmpbits))
 1743                 nonrefbit = 1;
 1744 
 1745         if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) {
 1746                 *reterrp = NFSERR_MOVED;
 1747                 return (0);
 1748         }
 1749 
 1750         /*
 1751          * Now we can fill in the attributes.
 1752          */
 1753         NFSSET_ATTRBIT(&tmpbits, retbitp);
 1754         NFSCLRNOT_ATTRBIT(&tmpbits, &refbits);
 1755 
 1756         /*
 1757          * Put out the attribute bitmap for the ones being filled in
 1758          * and get the field for the number of attributes returned.
 1759          */
 1760         prefixnum = nfsrv_putattrbit(nd, &tmpbits);
 1761         NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
 1762         prefixnum += NFSX_UNSIGNED;
 1763 
 1764         /*
 1765          * Now, loop around filling in the attributes for each bit set.
 1766          */
 1767         for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
 1768             if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) {
 1769                 switch (bitpos) {
 1770                 case NFSATTRBIT_TYPE:
 1771                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1772                         *tl = txdr_unsigned(NFDIR);
 1773                         retnum += NFSX_UNSIGNED;
 1774                         break;
 1775                 case NFSATTRBIT_FSID:
 1776                         NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
 1777                         *tl++ = 0;
 1778                         *tl++ = txdr_unsigned(NFSV4ROOT_FSID0);
 1779                         *tl++ = 0;
 1780                         *tl = txdr_unsigned(NFSV4ROOT_REFERRAL);
 1781                         retnum += NFSX_V4FSID;
 1782                         break;
 1783                 case NFSATTRBIT_RDATTRERROR:
 1784                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1785                         if (nonrefbit)
 1786                                 *tl = txdr_unsigned(NFSERR_MOVED);
 1787                         else
 1788                                 *tl = 0;
 1789                         retnum += NFSX_UNSIGNED;
 1790                         break;
 1791                 case NFSATTRBIT_FSLOCATIONS:
 1792                         retnum += nfsm_strtom(nd, "/", 1);
 1793                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1794                         *tl = txdr_unsigned(refp->nfr_srvcnt);
 1795                         retnum += NFSX_UNSIGNED;
 1796                         cp = refp->nfr_srvlist;
 1797                         for (i = 0; i < refp->nfr_srvcnt; i++) {
 1798                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1799                                 *tl = txdr_unsigned(1);
 1800                                 retnum += NFSX_UNSIGNED;
 1801                                 cp2 = STRCHR(cp, ':');
 1802                                 if (cp2 != NULL)
 1803                                         len = cp2 - cp;
 1804                                 else
 1805                                         len = 1;
 1806                                 retnum += nfsm_strtom(nd, cp, len);
 1807                                 if (cp2 != NULL)
 1808                                         cp = cp2 + 1;
 1809                                 cp2 = STRCHR(cp, ',');
 1810                                 if (cp2 != NULL)
 1811                                         len = cp2 - cp;
 1812                                 else
 1813                                         len = strlen(cp);
 1814                                 retnum += nfsm_strtom(nd, cp, len);
 1815                                 if (cp2 != NULL)
 1816                                         cp = cp2 + 1;
 1817                         }
 1818                         break;
 1819                 case NFSATTRBIT_MOUNTEDONFILEID:
 1820                         NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
 1821                         txdr_hyper(refp->nfr_dfileno, tl);
 1822                         retnum += NFSX_HYPER;
 1823                         break;
 1824                 default:
 1825                         printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos);
 1826                 }
 1827             }
 1828         }
 1829         *retnump = txdr_unsigned(retnum);
 1830         return (retnum + prefixnum);
 1831 }
 1832 
 1833 /*
 1834  * Parse a file name out of a request.
 1835  */
 1836 APPLESTATIC int
 1837 nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
 1838     NFSPATHLEN_T *outlenp)
 1839 {
 1840         char *fromcp, *tocp, val = '\0';
 1841         mbuf_t md;
 1842         int i;
 1843         int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0;
 1844         char digit;
 1845         u_int32_t *tl;
 1846         u_long hash = 0;
 1847 
 1848         if (hashp != NULL)
 1849                 *hashp = 0;
 1850         tocp = bufp;
 1851         /*
 1852          * For V4, check for lookup parent.
 1853          * Otherwise, get the component name.
 1854          */
 1855         if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
 1856             *tocp++ = '.';
 1857             hash += ((u_char)'.');
 1858             *tocp++ = '.';
 1859             hash += ((u_char)'.');
 1860             outlen = 2;
 1861         } else {
 1862             /*
 1863              * First, get the name length.
 1864              */
 1865             NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1866             len = fxdr_unsigned(int, *tl);
 1867             if (len > NFS_MAXNAMLEN) {
 1868                 nd->nd_repstat = NFSERR_NAMETOL;
 1869                 error = 0;
 1870                 goto nfsmout;
 1871             } else if (len <= 0) {
 1872                 nd->nd_repstat = NFSERR_INVAL;
 1873                 error = 0;
 1874                 goto nfsmout;
 1875             }
 1876 
 1877             /*
 1878              * Now, copy the component name into the buffer.
 1879              */
 1880             fromcp = nd->nd_dpos;
 1881             md = nd->nd_md;
 1882             rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp;
 1883             for (i = 0; i < len; i++) {
 1884                 while (rem == 0) {
 1885                         md = mbuf_next(md);
 1886                         if (md == NULL) {
 1887                                 error = EBADRPC;
 1888                                 goto nfsmout;
 1889                         }
 1890                         fromcp = NFSMTOD(md, caddr_t);
 1891                         rem = mbuf_len(md);
 1892                 }
 1893                 if (*fromcp == '\0') {
 1894                         nd->nd_repstat = EACCES;
 1895                         error = 0;
 1896                         goto nfsmout;
 1897                 }
 1898                 /*
 1899                  * For lookups on the public filehandle, do some special
 1900                  * processing on the name. (The public file handle is the
 1901                  * root of the public file system for this server.)
 1902                  */
 1903                 if (nd->nd_flag & ND_PUBLOOKUP) {
 1904                         /*
 1905                          * If the first char is ASCII, it is a canonical
 1906                          * path, otherwise it is a native path. (RFC2054
 1907                          * doesn't actually state what it is if the first
 1908                          * char isn't ASCII or 0x80, so I assume native.)
 1909                          * pubtype == 1 -> native path
 1910                          * pubtype == 2 -> canonical path
 1911                          */
 1912                         if (i == 0) {
 1913                                 if (*fromcp & 0x80) {
 1914                                         /*
 1915                                          * Since RFC2054 doesn't indicate
 1916                                          * that a native path of just 0x80
 1917                                          * isn't allowed, I'll replace the
 1918                                          * 0x80 with '/' instead of just
 1919                                          * throwing it away.
 1920                                          */
 1921                                         *fromcp = '/';
 1922                                         pubtype = 1;
 1923                                 } else {
 1924                                         pubtype = 2;
 1925                                 }
 1926                         }
 1927                         /*
 1928                          * '/' only allowed in a native path
 1929                          */
 1930                         if (*fromcp == '/' && pubtype != 1) {
 1931                                 nd->nd_repstat = EACCES;
 1932                                 error = 0;
 1933                                 goto nfsmout;
 1934                         }
 1935 
 1936                         /*
 1937                          * For the special case of 2 hex digits after a
 1938                          * '%' in an absolute path, calculate the value.
 1939                          * percent == 1 -> indicates "get first hex digit"
 1940                          * percent == 2 -> indicates "get second hex digit"
 1941                          */
 1942                         if (percent > 0) {
 1943                                 digit = nfsrv_hexdigit(*fromcp, &error);
 1944                                 if (error) {
 1945                                         nd->nd_repstat = EACCES;
 1946                                         error = 0;
 1947                                         goto nfsmout;
 1948                                 }
 1949                                 if (percent == 1) {
 1950                                         val = (digit << 4);
 1951                                         percent = 2;
 1952                                 } else {
 1953                                         val += digit;
 1954                                         percent = 0;
 1955                                         *tocp++ = val;
 1956                                         hash += ((u_char)val);
 1957                                         outlen++;
 1958                                 }
 1959                         } else {
 1960                                 if (*fromcp == '%' && pubtype == 2) {
 1961                                         /*
 1962                                          * Must be followed by 2 hex digits
 1963                                          */
 1964                                         if ((len - i) < 3) {
 1965                                                 nd->nd_repstat = EACCES;
 1966                                                 error = 0;
 1967                                                 goto nfsmout;
 1968                                         }
 1969                                         percent = 1;
 1970                                 } else {
 1971                                         *tocp++ = *fromcp;
 1972                                         hash += ((u_char)*fromcp);
 1973                                         outlen++;
 1974                                 }
 1975                         }
 1976                 } else {
 1977                         /*
 1978                          * Normal, non lookup on public, name.
 1979                          */
 1980                         if (*fromcp == '/') {
 1981                                 if (nd->nd_flag & ND_NFSV4)
 1982                                         nd->nd_repstat = NFSERR_BADNAME;
 1983                                 else
 1984                                         nd->nd_repstat = EACCES;
 1985                                 error = 0;
 1986                                 goto nfsmout;
 1987                         }
 1988                         hash += ((u_char)*fromcp);
 1989                         *tocp++ = *fromcp;
 1990                         outlen++;
 1991                 }
 1992                 fromcp++;
 1993                 rem--;
 1994             }
 1995             nd->nd_md = md;
 1996             nd->nd_dpos = fromcp;
 1997             i = NFSM_RNDUP(len) - len;
 1998             if (i > 0) {
 1999                 if (rem >= i) {
 2000                         nd->nd_dpos += i;
 2001                 } else {
 2002                         error = nfsm_advance(nd, i, rem);
 2003                         if (error)
 2004                                 goto nfsmout;
 2005                 }
 2006             }
 2007 
 2008             /*
 2009              * For v4, don't allow lookups of '.' or '..' and
 2010              * also check for non-utf8 strings.
 2011              */
 2012             if (nd->nd_flag & ND_NFSV4) {
 2013                 if ((outlen == 1 && bufp[0] == '.') ||
 2014                     (outlen == 2 && bufp[0] == '.' &&
 2015                      bufp[1] == '.')) {
 2016                     nd->nd_repstat = NFSERR_BADNAME;
 2017                     error = 0;
 2018                     goto nfsmout;
 2019                 }
 2020                 if (enable_checkutf8 == 1 &&
 2021                     nfsrv_checkutf8((u_int8_t *)bufp, outlen)) {
 2022                     nd->nd_repstat = NFSERR_INVAL;
 2023                     error = 0;
 2024                     goto nfsmout;
 2025                 }
 2026             }
 2027         }
 2028         *tocp = '\0';
 2029         *outlenp = (size_t)outlen;
 2030         if (hashp != NULL)
 2031                 *hashp = hash;
 2032 nfsmout:
 2033         NFSEXITCODE2(error, nd);
 2034         return (error);
 2035 }
 2036 
 2037 void
 2038 nfsd_init(void)
 2039 {
 2040         int i;
 2041         static int inited = 0;
 2042 
 2043         if (inited)
 2044                 return;
 2045         inited = 1;
 2046 
 2047         /*
 2048          * Initialize client queues. Don't free/reinitialize
 2049          * them when nfsds are restarted.
 2050          */
 2051         nfsclienthash = malloc(sizeof(struct nfsclienthashhead) *
 2052             nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO);
 2053         for (i = 0; i < nfsrv_clienthashsize; i++)
 2054                 LIST_INIT(&nfsclienthash[i]);
 2055         nfslockhash = malloc(sizeof(struct nfslockhashhead) *
 2056             nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO);
 2057         for (i = 0; i < nfsrv_lockhashsize; i++)
 2058                 LIST_INIT(&nfslockhash[i]);
 2059         nfssessionhash = malloc(sizeof(struct nfssessionhash) *
 2060             nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO);
 2061         for (i = 0; i < nfsrv_sessionhashsize; i++) {
 2062                 mtx_init(&nfssessionhash[i].mtx, "nfssm", NULL, MTX_DEF);
 2063                 LIST_INIT(&nfssessionhash[i].list);
 2064         }
 2065         LIST_INIT(&nfsrv_dontlisthead);
 2066         TAILQ_INIT(&nfsrv_recalllisthead);
 2067 
 2068         /* and the v2 pubfh should be all zeros */
 2069         NFSBZERO(nfs_v2pubfh, NFSX_V2FH);
 2070 }
 2071 
 2072 /*
 2073  * Check the v4 root exports.
 2074  * Return 0 if ok, 1 otherwise.
 2075  */
 2076 int
 2077 nfsd_checkrootexp(struct nfsrv_descript *nd)
 2078 {
 2079 
 2080         if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
 2081                 return (0);
 2082         if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
 2083             (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY))
 2084                 return (0);
 2085         if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) ==
 2086             (ND_GSSPRIVACY | ND_EXGSSPRIVACY))
 2087                 return (0);
 2088         if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
 2089              ND_EXGSS)) == (ND_GSS | ND_EXGSS))
 2090                 return (0);
 2091         return (1);
 2092 }
 2093 
 2094 /*
 2095  * Parse the first part of an NFSv4 compound to find out what the minor
 2096  * version# is.
 2097  */
 2098 void
 2099 nfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp,
 2100     int *taglenp, u_int32_t *minversp)
 2101 {
 2102         uint32_t *tl;
 2103         int error = 0, taglen = -1;
 2104         u_char *tagstr = NULL;
 2105 
 2106         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 2107         taglen = fxdr_unsigned(int, *tl);
 2108         if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) {
 2109                 error = EBADRPC;
 2110                 goto nfsmout;
 2111         }
 2112         if (taglen <= NFSV4_SMALLSTR)
 2113                 tagstr = tag;
 2114         else
 2115                 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
 2116         error = nfsrv_mtostr(nd, tagstr, taglen);
 2117         if (error != 0)
 2118                 goto nfsmout;
 2119         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 2120         *minversp = fxdr_unsigned(u_int32_t, *tl);
 2121         *tagstrp = tagstr;
 2122         if (*minversp == NFSV41_MINORVERSION)
 2123                 nd->nd_flag |= ND_NFSV41;
 2124 nfsmout:
 2125         if (error != 0) {
 2126                 if (tagstr != NULL && taglen > NFSV4_SMALLSTR)
 2127                         free(tagstr, M_TEMP);
 2128                 taglen = -1;
 2129         }
 2130         *taglenp = taglen;
 2131 }
 2132 

Cache object: 2be3c6dd169bee48e7c6d137e4d54c31


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.