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

Cache object: c288e7b6d730723e4dbd1513bd4d40e8


[ 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.