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

Cache object: 35f08b71fe9aa6f016c90af7816044bc


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