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  * A fiddled version of m_adj() that ensures null fill to a long
 1272  * boundary and only trims off the back end
 1273  */
 1274 void
 1275 nfsrv_adj(mbuf_t mp, int len, int nul)
 1276 {
 1277         mbuf_t m;
 1278         int count, i;
 1279         char *cp;
 1280 
 1281         /*
 1282          * Trim from tail.  Scan the mbuf chain,
 1283          * calculating its length and finding the last mbuf.
 1284          * If the adjustment only affects this mbuf, then just
 1285          * adjust and return.  Otherwise, rescan and truncate
 1286          * after the remaining size.
 1287          */
 1288         count = 0;
 1289         m = mp;
 1290         for (;;) {
 1291                 count += mbuf_len(m);
 1292                 if (mbuf_next(m) == NULL)
 1293                         break;
 1294                 m = mbuf_next(m);
 1295         }
 1296         if (mbuf_len(m) > len) {
 1297                 mbuf_setlen(m, mbuf_len(m) - len);
 1298                 if (nul > 0) {
 1299                         cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
 1300                         for (i = 0; i < nul; i++)
 1301                                 *cp++ = '\0';
 1302                 }
 1303                 return;
 1304         }
 1305         count -= len;
 1306         if (count < 0)
 1307                 count = 0;
 1308         /*
 1309          * Correct length for chain is "count".
 1310          * Find the mbuf with last data, adjust its length,
 1311          * and toss data from remaining mbufs on chain.
 1312          */
 1313         for (m = mp; m; m = mbuf_next(m)) {
 1314                 if (mbuf_len(m) >= count) {
 1315                         mbuf_setlen(m, count);
 1316                         if (nul > 0) {
 1317                                 cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
 1318                                 for (i = 0; i < nul; i++)
 1319                                         *cp++ = '\0';
 1320                         }
 1321                         break;
 1322                 }
 1323                 count -= mbuf_len(m);
 1324         }
 1325         for (m = mbuf_next(m); m; m = mbuf_next(m))
 1326                 mbuf_setlen(m, 0);
 1327 }
 1328 
 1329 /*
 1330  * Make these functions instead of macros, so that the kernel text size
 1331  * doesn't get too big...
 1332  */
 1333 void
 1334 nfsrv_wcc(struct nfsrv_descript *nd, int before_ret,
 1335     struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap)
 1336 {
 1337         u_int32_t *tl;
 1338 
 1339         if (before_ret) {
 1340                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1341                 *tl = newnfs_false;
 1342         } else {
 1343                 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 1344                 *tl++ = newnfs_true;
 1345                 txdr_hyper(before_nvap->na_size, tl);
 1346                 tl += 2;
 1347                 txdr_nfsv3time(&(before_nvap->na_mtime), tl);
 1348                 tl += 2;
 1349                 txdr_nfsv3time(&(before_nvap->na_ctime), tl);
 1350         }
 1351         nfsrv_postopattr(nd, after_ret, after_nvap);
 1352 }
 1353 
 1354 void
 1355 nfsrv_postopattr(struct nfsrv_descript *nd, int after_ret,
 1356     struct nfsvattr *after_nvap)
 1357 {
 1358         u_int32_t *tl;
 1359 
 1360         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1361         if (after_ret)
 1362                 *tl = newnfs_false;
 1363         else {
 1364                 *tl = newnfs_true;
 1365                 nfsrv_fillattr(nd, after_nvap);
 1366         }
 1367 }
 1368 
 1369 /*
 1370  * Fill in file attributes for V2 and 3. For V4, call a separate
 1371  * routine that sifts through all the attribute bits.
 1372  */
 1373 void
 1374 nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap)
 1375 {
 1376         struct nfs_fattr *fp;
 1377         int fattr_size;
 1378 
 1379         /*
 1380          * Build space for the attribute structure.
 1381          */
 1382         if (nd->nd_flag & ND_NFSV3)
 1383                 fattr_size = NFSX_V3FATTR;
 1384         else
 1385                 fattr_size = NFSX_V2FATTR;
 1386         NFSM_BUILD(fp, struct nfs_fattr *, fattr_size);
 1387 
 1388         /*
 1389          * Now just fill it all in.
 1390          */
 1391         fp->fa_nlink = txdr_unsigned(nvap->na_nlink);
 1392         fp->fa_uid = txdr_unsigned(nvap->na_uid);
 1393         fp->fa_gid = txdr_unsigned(nvap->na_gid);
 1394         if (nd->nd_flag & ND_NFSV3) {
 1395                 fp->fa_type = vtonfsv34_type(nvap->na_type);
 1396                 fp->fa_mode = vtonfsv34_mode(nvap->na_mode);
 1397                 txdr_hyper(nvap->na_size, (uint32_t*)&fp->fa3_size);
 1398                 txdr_hyper(nvap->na_bytes, (uint32_t*)&fp->fa3_used);
 1399                 fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev));
 1400                 fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev));
 1401                 fp->fa3_fsid.nfsuquad[0] = 0;
 1402                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid);
 1403                 txdr_hyper(nvap->na_fileid, (uint32_t*)&fp->fa3_fileid);
 1404                 txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime);
 1405                 txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime);
 1406                 txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime);
 1407         } else {
 1408                 fp->fa_type = vtonfsv2_type(nvap->na_type);
 1409                 fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode);
 1410                 fp->fa2_size = txdr_unsigned(nvap->na_size);
 1411                 fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize);
 1412                 if (nvap->na_type == VFIFO)
 1413                         fp->fa2_rdev = 0xffffffff;
 1414                 else
 1415                         fp->fa2_rdev = txdr_unsigned(nvap->na_rdev);
 1416                 fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE);
 1417                 fp->fa2_fsid = txdr_unsigned(nvap->na_fsid);
 1418                 fp->fa2_fileid = txdr_unsigned(nvap->na_fileid);
 1419                 txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime);
 1420                 txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime);
 1421                 txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime);
 1422         }
 1423 }
 1424 
 1425 /*
 1426  * This function gets a file handle out of an mbuf list.
 1427  * It returns 0 for success, EBADRPC otherwise.
 1428  * If sets the third flagp argument to 1 if the file handle is
 1429  * the public file handle.
 1430  * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE
 1431  */
 1432 int
 1433 nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
 1434 {
 1435         u_int32_t *tl;
 1436         int error = 0, len, copylen;
 1437 
 1438         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1439                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1440                 len = fxdr_unsigned(int, *tl);
 1441                 if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) &&
 1442                     nd->nd_procnum == NFSPROC_LOOKUP) {
 1443                         nd->nd_flag |= ND_PUBLOOKUP;
 1444                         goto nfsmout;
 1445                 }
 1446                 copylen = len;
 1447 
 1448                 /* If len == NFSX_V4PNFSFH the RPC is a pNFS DS one. */
 1449                 if (len == NFSX_V4PNFSFH && (nd->nd_flag & ND_NFSV41) != 0) {
 1450                         copylen = NFSX_MYFH;
 1451                         len = NFSM_RNDUP(len);
 1452                         nd->nd_flag |= ND_DSSERVER;
 1453                 } else if (len < NFSRV_MINFH || len > NFSRV_MAXFH) {
 1454                         if (nd->nd_flag & ND_NFSV4) {
 1455                             if (len > 0 && len <= NFSX_V4FHMAX) {
 1456                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 1457                                 if (error)
 1458                                         goto nfsmout;
 1459                                 nd->nd_repstat = NFSERR_BADHANDLE;
 1460                                 goto nfsmout;
 1461                             } else {
 1462                                     error = EBADRPC;
 1463                                     goto nfsmout;
 1464                             }
 1465                         } else {
 1466                                 error = EBADRPC;
 1467                                 goto nfsmout;
 1468                         }
 1469                 }
 1470         } else {
 1471                 /*
 1472                  * For NFSv2, the file handle is always 32 bytes on the
 1473                  * wire, but this server only cares about the first
 1474                  * NFSRV_MAXFH bytes.
 1475                  */
 1476                 len = NFSX_V2FH;
 1477                 copylen = NFSRV_MAXFH;
 1478         }
 1479         NFSM_DISSECT(tl, u_int32_t *, len);
 1480         if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset &&
 1481             nd->nd_procnum == NFSPROC_LOOKUP &&
 1482             !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) {
 1483                 nd->nd_flag |= ND_PUBLOOKUP;
 1484                 goto nfsmout;
 1485         }
 1486         NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen);
 1487         fhp->nfsrvfh_len = copylen;
 1488 nfsmout:
 1489         NFSEXITCODE2(error, nd);
 1490         return (error);
 1491 }
 1492 
 1493 /*
 1494  * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error
 1495  * numbers not specified for the associated procedure.
 1496  * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat
 1497  * should be cleared. NFSPROC_NOOP is used to return errors when a valid
 1498  * RPC procedure is not involved.
 1499  * Returns the error number in XDR.
 1500  */
 1501 int
 1502 nfsd_errmap(struct nfsrv_descript *nd)
 1503 {
 1504         short *defaulterrp, *errp;
 1505 
 1506         if (!nd->nd_repstat)
 1507                 return (0);
 1508         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1509                 if (nd->nd_procnum == NFSPROC_NOOP)
 1510                         return (txdr_unsigned(nd->nd_repstat & 0xffff));
 1511                 if (nd->nd_flag & ND_NFSV3)
 1512                     errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
 1513                 else if (nd->nd_repstat == EBADRPC)
 1514                         return (txdr_unsigned(NFSERR_BADXDR));
 1515                 else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH ||
 1516                          nd->nd_repstat == NFSERR_OPILLEGAL)
 1517                         return (txdr_unsigned(nd->nd_repstat));
 1518                 else if (nd->nd_repstat == NFSERR_REPLYFROMCACHE)
 1519                         return (txdr_unsigned(NFSERR_IO));
 1520                 else if ((nd->nd_flag & ND_NFSV41) != 0) {
 1521                         if (nd->nd_repstat == EOPNOTSUPP)
 1522                                 nd->nd_repstat = NFSERR_NOTSUPP;
 1523                         nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat);
 1524                         return (txdr_unsigned(nd->nd_repstat));
 1525                 } else
 1526                     errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum];
 1527                 while (*++errp)
 1528                         if (*errp == nd->nd_repstat)
 1529                                 return (txdr_unsigned(nd->nd_repstat));
 1530                 return (txdr_unsigned(*defaulterrp));
 1531         }
 1532         if (nd->nd_repstat <= NFSERR_REMOTE)
 1533                 return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1]));
 1534         return (txdr_unsigned(NFSERR_IO));
 1535 }
 1536 
 1537 /*
 1538  * Check to see if the error is a valid NFS one. If not, replace it with
 1539  * NFSERR_IO.
 1540  */
 1541 static u_int32_t
 1542 nfsrv_isannfserr(u_int32_t errval)
 1543 {
 1544 
 1545         if (errval == NFSERR_OK)
 1546                 return (errval);
 1547         if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_DELEGREVOKED)
 1548                 return (errval);
 1549         if (errval > 0 && errval <= NFSERR_REMOTE)
 1550                 return (nfsrv_v2errmap[errval - 1]);
 1551         return (NFSERR_IO);
 1552 }
 1553 
 1554 /*
 1555  * Check to see if setting a uid/gid is permitted when creating a new
 1556  * file object. (Called when uid and/or gid is specified in the
 1557  * settable attributes for V4.
 1558  */
 1559 int
 1560 nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap)
 1561 {
 1562         int error = 0;
 1563 
 1564         /*
 1565          * If not setting either uid nor gid, it's OK.
 1566          */
 1567         if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap))
 1568                 goto out;
 1569         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid &&
 1570            enable_nobodycheck == 1)
 1571             || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid &&
 1572            enable_nogroupcheck == 1)) {
 1573                 error = NFSERR_BADOWNER;
 1574                 goto out;
 1575         }
 1576         if (nd->nd_cred->cr_uid == 0)
 1577                 goto out;
 1578         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) ||
 1579             (NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid &&
 1580             !groupmember(nvap->na_gid, nd->nd_cred)))
 1581                 error = NFSERR_PERM;
 1582 
 1583 out:
 1584         NFSEXITCODE2(error, nd);
 1585         return (error);
 1586 }
 1587 
 1588 /*
 1589  * and this routine fixes up the settable attributes for V4 if allowed
 1590  * by nfsrv_checkuidgid().
 1591  */
 1592 void
 1593 nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
 1594     struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp,
 1595     struct nfsexstuff *exp)
 1596 {
 1597         int change = 0;
 1598         struct nfsvattr nva;
 1599         uid_t tuid;
 1600         int error;
 1601         nfsattrbit_t nattrbits;
 1602 
 1603         /*
 1604          * Maybe this should be done for V2 and 3 but it never has been
 1605          * and nobody seems to be upset, so I think it's best not to change
 1606          * the V2 and 3 semantics.
 1607          */
 1608         if ((nd->nd_flag & ND_NFSV4) == 0)
 1609                 goto out;
 1610         NFSVNO_ATTRINIT(&nva);
 1611         NFSZERO_ATTRBIT(&nattrbits);
 1612         tuid = nd->nd_cred->cr_uid;
 1613         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) &&
 1614             NFSVNO_ISSETUID(nvap) &&
 1615             nvap->na_uid != nd->nd_cred->cr_uid) {
 1616                 if (nd->nd_cred->cr_uid == 0) {
 1617                         nva.na_uid = nvap->na_uid;
 1618                         change++;
 1619                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER);
 1620                 } else {
 1621                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER);
 1622                 }
 1623         }
 1624         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) &&
 1625             NFSVNO_ISSETATIME(nvap)) {
 1626                 nva.na_atime = nvap->na_atime;
 1627                 change++;
 1628                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET);
 1629         }
 1630         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) &&
 1631             NFSVNO_ISSETMTIME(nvap)) {
 1632                 nva.na_mtime = nvap->na_mtime;
 1633                 change++;
 1634                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET);
 1635         }
 1636         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) &&
 1637             NFSVNO_ISSETGID(nvap)) {
 1638                 if (nvap->na_gid == nd->nd_cred->cr_gid ||
 1639                     groupmember(nvap->na_gid, nd->nd_cred)) {
 1640                         nd->nd_cred->cr_uid = 0;
 1641                         nva.na_gid = nvap->na_gid;
 1642                         change++;
 1643                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP);
 1644                 } else {
 1645                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
 1646                 }
 1647         }
 1648         if (change) {
 1649                 error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
 1650                 if (error) {
 1651                         NFSCLRALL_ATTRBIT(attrbitp, &nattrbits);
 1652                 }
 1653         }
 1654         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) &&
 1655             NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) {
 1656                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE);
 1657         }
 1658 #ifdef NFS4_ACL_EXTATTR_NAME
 1659         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) &&
 1660             nfsrv_useacl != 0 && aclp != NULL) {
 1661                 if (aclp->acl_cnt > 0) {
 1662                         error = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
 1663                         if (error) {
 1664                                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
 1665                         }
 1666                 }
 1667         } else
 1668 #endif
 1669         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
 1670         nd->nd_cred->cr_uid = tuid;
 1671 
 1672 out:
 1673         NFSEXITCODE2(0, nd);
 1674 }
 1675 
 1676 /*
 1677  * Translate an ASCII hex digit to it's binary value. Return -1 if the
 1678  * char isn't a hex digit.
 1679  */
 1680 static char
 1681 nfsrv_hexdigit(char c, int *err)
 1682 {
 1683 
 1684         *err = 0;
 1685         if (c >= '' && c <= '9')
 1686                 return (c - '');
 1687         if (c >= 'a' && c <= 'f')
 1688                 return (c - 'a' + ((char)10));
 1689         if (c >= 'A' && c <= 'F')
 1690                 return (c - 'A' + ((char)10));
 1691         /* Not valid ! */
 1692         *err = 1;
 1693         return (1);     /* BOGUS */
 1694 }
 1695 
 1696 /*
 1697  * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff
 1698  * it can be.
 1699  */
 1700 int
 1701 nfsrv_errmoved(int op)
 1702 {
 1703         short *errp;
 1704 
 1705         errp = nfsrv_v4errmap[op];
 1706         while (*errp != 0) {
 1707                 if (*errp == NFSERR_MOVED)
 1708                         return (1);
 1709                 errp++;
 1710         }
 1711         return (0);
 1712 }
 1713 
 1714 /*
 1715  * Fill in attributes for a Referral.
 1716  * (Return the number of bytes of XDR created.)
 1717  */
 1718 int
 1719 nfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp,
 1720     struct nfsreferral *refp, int getattr, int *reterrp)
 1721 {
 1722         u_int32_t *tl, *retnump;
 1723         u_char *cp, *cp2;
 1724         int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0;
 1725         int fslocationsbit = 0;
 1726         nfsattrbit_t tmpbits, refbits;
 1727 
 1728         NFSREFERRAL_ATTRBIT(&refbits);
 1729         if (getattr)
 1730                 NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR);
 1731         else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR))
 1732                 rderrbit = 1;
 1733         if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS))
 1734                 fslocationsbit = 1;
 1735 
 1736         /*
 1737          * Check for the case where unsupported referral attributes are
 1738          * requested.
 1739          */
 1740         NFSSET_ATTRBIT(&tmpbits, retbitp);
 1741         NFSCLRALL_ATTRBIT(&tmpbits, &refbits);
 1742         if (NFSNONZERO_ATTRBIT(&tmpbits))
 1743                 nonrefbit = 1;
 1744 
 1745         if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) {
 1746                 *reterrp = NFSERR_MOVED;
 1747                 return (0);
 1748         }
 1749 
 1750         /*
 1751          * Now we can fill in the attributes.
 1752          */
 1753         NFSSET_ATTRBIT(&tmpbits, retbitp);
 1754         NFSCLRNOT_ATTRBIT(&tmpbits, &refbits);
 1755 
 1756         /*
 1757          * Put out the attribute bitmap for the ones being filled in
 1758          * and get the field for the number of attributes returned.
 1759          */
 1760         prefixnum = nfsrv_putattrbit(nd, &tmpbits);
 1761         NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
 1762         prefixnum += NFSX_UNSIGNED;
 1763 
 1764         /*
 1765          * Now, loop around filling in the attributes for each bit set.
 1766          */
 1767         for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
 1768             if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) {
 1769                 switch (bitpos) {
 1770                 case NFSATTRBIT_TYPE:
 1771                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1772                         *tl = txdr_unsigned(NFDIR);
 1773                         retnum += NFSX_UNSIGNED;
 1774                         break;
 1775                 case NFSATTRBIT_FSID:
 1776                         NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
 1777                         *tl++ = 0;
 1778                         *tl++ = txdr_unsigned(NFSV4ROOT_FSID0);
 1779                         *tl++ = 0;
 1780                         *tl = txdr_unsigned(NFSV4ROOT_REFERRAL);
 1781                         retnum += NFSX_V4FSID;
 1782                         break;
 1783                 case NFSATTRBIT_RDATTRERROR:
 1784                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1785                         if (nonrefbit)
 1786                                 *tl = txdr_unsigned(NFSERR_MOVED);
 1787                         else
 1788                                 *tl = 0;
 1789                         retnum += NFSX_UNSIGNED;
 1790                         break;
 1791                 case NFSATTRBIT_FSLOCATIONS:
 1792                         retnum += nfsm_strtom(nd, "/", 1);
 1793                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1794                         *tl = txdr_unsigned(refp->nfr_srvcnt);
 1795                         retnum += NFSX_UNSIGNED;
 1796                         cp = refp->nfr_srvlist;
 1797                         for (i = 0; i < refp->nfr_srvcnt; i++) {
 1798                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1799                                 *tl = txdr_unsigned(1);
 1800                                 retnum += NFSX_UNSIGNED;
 1801                                 cp2 = STRCHR(cp, ':');
 1802                                 if (cp2 != NULL)
 1803                                         len = cp2 - cp;
 1804                                 else
 1805                                         len = 1;
 1806                                 retnum += nfsm_strtom(nd, cp, len);
 1807                                 if (cp2 != NULL)
 1808                                         cp = cp2 + 1;
 1809                                 cp2 = STRCHR(cp, ',');
 1810                                 if (cp2 != NULL)
 1811                                         len = cp2 - cp;
 1812                                 else
 1813                                         len = strlen(cp);
 1814                                 retnum += nfsm_strtom(nd, cp, len);
 1815                                 if (cp2 != NULL)
 1816                                         cp = cp2 + 1;
 1817                         }
 1818                         break;
 1819                 case NFSATTRBIT_MOUNTEDONFILEID:
 1820                         NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
 1821                         txdr_hyper(refp->nfr_dfileno, tl);
 1822                         retnum += NFSX_HYPER;
 1823                         break;
 1824                 default:
 1825                         printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos);
 1826                 }
 1827             }
 1828         }
 1829         *retnump = txdr_unsigned(retnum);
 1830         return (retnum + prefixnum);
 1831 }
 1832 
 1833 /*
 1834  * Parse a file name out of a request.
 1835  */
 1836 int
 1837 nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
 1838     NFSPATHLEN_T *outlenp)
 1839 {
 1840         char *fromcp, *tocp, val = '\0';
 1841         mbuf_t md;
 1842         int i;
 1843         int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0;
 1844         char digit;
 1845         u_int32_t *tl;
 1846         u_long hash = 0;
 1847 
 1848         if (hashp != NULL)
 1849                 *hashp = 0;
 1850         tocp = bufp;
 1851         /*
 1852          * For V4, check for lookup parent.
 1853          * Otherwise, get the component name.
 1854          */
 1855         if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
 1856             *tocp++ = '.';
 1857             hash += ((u_char)'.');
 1858             *tocp++ = '.';
 1859             hash += ((u_char)'.');
 1860             outlen = 2;
 1861         } else {
 1862             /*
 1863              * First, get the name length.
 1864              */
 1865             NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1866             len = fxdr_unsigned(int, *tl);
 1867             if (len > NFS_MAXNAMLEN) {
 1868                 nd->nd_repstat = NFSERR_NAMETOL;
 1869                 error = 0;
 1870                 goto nfsmout;
 1871             } else if (len <= 0) {
 1872                 nd->nd_repstat = NFSERR_INVAL;
 1873                 error = 0;
 1874                 goto nfsmout;
 1875             }
 1876 
 1877             /*
 1878              * Now, copy the component name into the buffer.
 1879              */
 1880             fromcp = nd->nd_dpos;
 1881             md = nd->nd_md;
 1882             rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp;
 1883             for (i = 0; i < len; i++) {
 1884                 while (rem == 0) {
 1885                         md = mbuf_next(md);
 1886                         if (md == NULL) {
 1887                                 error = EBADRPC;
 1888                                 goto nfsmout;
 1889                         }
 1890                         fromcp = NFSMTOD(md, caddr_t);
 1891                         rem = mbuf_len(md);
 1892                 }
 1893                 if (*fromcp == '\0') {
 1894                         nd->nd_repstat = EACCES;
 1895                         error = 0;
 1896                         goto nfsmout;
 1897                 }
 1898                 /*
 1899                  * For lookups on the public filehandle, do some special
 1900                  * processing on the name. (The public file handle is the
 1901                  * root of the public file system for this server.)
 1902                  */
 1903                 if (nd->nd_flag & ND_PUBLOOKUP) {
 1904                         /*
 1905                          * If the first char is ASCII, it is a canonical
 1906                          * path, otherwise it is a native path. (RFC2054
 1907                          * doesn't actually state what it is if the first
 1908                          * char isn't ASCII or 0x80, so I assume native.)
 1909                          * pubtype == 1 -> native path
 1910                          * pubtype == 2 -> canonical path
 1911                          */
 1912                         if (i == 0) {
 1913                                 if (*fromcp & 0x80) {
 1914                                         /*
 1915                                          * Since RFC2054 doesn't indicate
 1916                                          * that a native path of just 0x80
 1917                                          * isn't allowed, I'll replace the
 1918                                          * 0x80 with '/' instead of just
 1919                                          * throwing it away.
 1920                                          */
 1921                                         *fromcp = '/';
 1922                                         pubtype = 1;
 1923                                 } else {
 1924                                         pubtype = 2;
 1925                                 }
 1926                         }
 1927                         /*
 1928                          * '/' only allowed in a native path
 1929                          */
 1930                         if (*fromcp == '/' && pubtype != 1) {
 1931                                 nd->nd_repstat = EACCES;
 1932                                 error = 0;
 1933                                 goto nfsmout;
 1934                         }
 1935 
 1936                         /*
 1937                          * For the special case of 2 hex digits after a
 1938                          * '%' in an absolute path, calculate the value.
 1939                          * percent == 1 -> indicates "get first hex digit"
 1940                          * percent == 2 -> indicates "get second hex digit"
 1941                          */
 1942                         if (percent > 0) {
 1943                                 digit = nfsrv_hexdigit(*fromcp, &error);
 1944                                 if (error) {
 1945                                         nd->nd_repstat = EACCES;
 1946                                         error = 0;
 1947                                         goto nfsmout;
 1948                                 }
 1949                                 if (percent == 1) {
 1950                                         val = (digit << 4);
 1951                                         percent = 2;
 1952                                 } else {
 1953                                         val += digit;
 1954                                         percent = 0;
 1955                                         *tocp++ = val;
 1956                                         hash += ((u_char)val);
 1957                                         outlen++;
 1958                                 }
 1959                         } else {
 1960                                 if (*fromcp == '%' && pubtype == 2) {
 1961                                         /*
 1962                                          * Must be followed by 2 hex digits
 1963                                          */
 1964                                         if ((len - i) < 3) {
 1965                                                 nd->nd_repstat = EACCES;
 1966                                                 error = 0;
 1967                                                 goto nfsmout;
 1968                                         }
 1969                                         percent = 1;
 1970                                 } else {
 1971                                         *tocp++ = *fromcp;
 1972                                         hash += ((u_char)*fromcp);
 1973                                         outlen++;
 1974                                 }
 1975                         }
 1976                 } else {
 1977                         /*
 1978                          * Normal, non lookup on public, name.
 1979                          */
 1980                         if (*fromcp == '/') {
 1981                                 if (nd->nd_flag & ND_NFSV4)
 1982                                         nd->nd_repstat = NFSERR_BADNAME;
 1983                                 else
 1984                                         nd->nd_repstat = EACCES;
 1985                                 error = 0;
 1986                                 goto nfsmout;
 1987                         }
 1988                         hash += ((u_char)*fromcp);
 1989                         *tocp++ = *fromcp;
 1990                         outlen++;
 1991                 }
 1992                 fromcp++;
 1993                 rem--;
 1994             }
 1995             nd->nd_md = md;
 1996             nd->nd_dpos = fromcp;
 1997             i = NFSM_RNDUP(len) - len;
 1998             if (i > 0) {
 1999                 if (rem >= i) {
 2000                         nd->nd_dpos += i;
 2001                 } else {
 2002                         error = nfsm_advance(nd, i, rem);
 2003                         if (error)
 2004                                 goto nfsmout;
 2005                 }
 2006             }
 2007 
 2008             /*
 2009              * For v4, don't allow lookups of '.' or '..' and
 2010              * also check for non-utf8 strings.
 2011              */
 2012             if (nd->nd_flag & ND_NFSV4) {
 2013                 if ((outlen == 1 && bufp[0] == '.') ||
 2014                     (outlen == 2 && bufp[0] == '.' &&
 2015                      bufp[1] == '.')) {
 2016                     nd->nd_repstat = NFSERR_BADNAME;
 2017                     error = 0;
 2018                     goto nfsmout;
 2019                 }
 2020                 if (enable_checkutf8 == 1 &&
 2021                     nfsrv_checkutf8((u_int8_t *)bufp, outlen)) {
 2022                     nd->nd_repstat = NFSERR_INVAL;
 2023                     error = 0;
 2024                     goto nfsmout;
 2025                 }
 2026             }
 2027         }
 2028         *tocp = '\0';
 2029         *outlenp = (size_t)outlen;
 2030         if (hashp != NULL)
 2031                 *hashp = hash;
 2032 nfsmout:
 2033         NFSEXITCODE2(error, nd);
 2034         return (error);
 2035 }
 2036 
 2037 void
 2038 nfsd_init(void)
 2039 {
 2040         int i;
 2041         static int inited = 0;
 2042 
 2043         if (inited)
 2044                 return;
 2045         inited = 1;
 2046 
 2047         /*
 2048          * Initialize client queues. Don't free/reinitialize
 2049          * them when nfsds are restarted.
 2050          */
 2051         nfsclienthash = malloc(sizeof(struct nfsclienthashhead) *
 2052             nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO);
 2053         for (i = 0; i < nfsrv_clienthashsize; i++)
 2054                 LIST_INIT(&nfsclienthash[i]);
 2055         nfslockhash = malloc(sizeof(struct nfslockhashhead) *
 2056             nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO);
 2057         for (i = 0; i < nfsrv_lockhashsize; i++)
 2058                 LIST_INIT(&nfslockhash[i]);
 2059         nfssessionhash = malloc(sizeof(struct nfssessionhash) *
 2060             nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO);
 2061         for (i = 0; i < nfsrv_sessionhashsize; i++) {
 2062                 mtx_init(&nfssessionhash[i].mtx, "nfssm", NULL, MTX_DEF);
 2063                 LIST_INIT(&nfssessionhash[i].list);
 2064         }
 2065         LIST_INIT(&nfsrv_dontlisthead);
 2066         TAILQ_INIT(&nfsrv_recalllisthead);
 2067 
 2068         /* and the v2 pubfh should be all zeros */
 2069         NFSBZERO(nfs_v2pubfh, NFSX_V2FH);
 2070 }
 2071 
 2072 /*
 2073  * Check the v4 root exports.
 2074  * Return 0 if ok, 1 otherwise.
 2075  */
 2076 int
 2077 nfsd_checkrootexp(struct nfsrv_descript *nd)
 2078 {
 2079 
 2080         if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
 2081                 return (0);
 2082         if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
 2083             (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY))
 2084                 return (0);
 2085         if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) ==
 2086             (ND_GSSPRIVACY | ND_EXGSSPRIVACY))
 2087                 return (0);
 2088         if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
 2089              ND_EXGSS)) == (ND_GSS | ND_EXGSS))
 2090                 return (0);
 2091         return (1);
 2092 }
 2093 
 2094 /*
 2095  * Parse the first part of an NFSv4 compound to find out what the minor
 2096  * version# is.
 2097  */
 2098 void
 2099 nfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp,
 2100     int *taglenp, u_int32_t *minversp)
 2101 {
 2102         uint32_t *tl;
 2103         int error = 0, taglen = -1;
 2104         u_char *tagstr = NULL;
 2105 
 2106         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 2107         taglen = fxdr_unsigned(int, *tl);
 2108         if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) {
 2109                 error = EBADRPC;
 2110                 goto nfsmout;
 2111         }
 2112         if (taglen <= NFSV4_SMALLSTR)
 2113                 tagstr = tag;
 2114         else
 2115                 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
 2116         error = nfsrv_mtostr(nd, tagstr, taglen);
 2117         if (error != 0)
 2118                 goto nfsmout;
 2119         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 2120         *minversp = fxdr_unsigned(u_int32_t, *tl);
 2121         *tagstrp = tagstr;
 2122         if (*minversp == NFSV41_MINORVERSION)
 2123                 nd->nd_flag |= ND_NFSV41;
 2124 nfsmout:
 2125         if (error != 0) {
 2126                 if (tagstr != NULL && taglen > NFSV4_SMALLSTR)
 2127                         free(tagstr, M_TEMP);
 2128                 taglen = -1;
 2129         }
 2130         *taglenp = taglen;
 2131 }
 2132 

Cache object: 7a71238b2ff43be7ba9bb5d46faf6f53


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