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

Cache object: 51624cf25394caa35352e7938c4638e1


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