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/nfsserver/nfs_srvsubs.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  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)nfs_subs.c  8.8 (Berkeley) 5/22/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/5.2/sys/nfsserver/nfs_srvsubs.c 116189 2003-06-11 05:37:42Z obrien $");
   41 
   42 /*
   43  * These functions support the macros and help fiddle mbuf chains for
   44  * the nfs op functions. They do things like create the rpc header and
   45  * copy data between mbuf chains and uio lists.
   46  */
   47 
   48 #include "opt_inet6.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/kernel.h>
   53 #include <sys/bio.h>
   54 #include <sys/buf.h>
   55 #include <sys/proc.h>
   56 #include <sys/mount.h>
   57 #include <sys/vnode.h>
   58 #include <sys/namei.h>
   59 #include <sys/mbuf.h>
   60 #include <sys/socket.h>
   61 #include <sys/stat.h>
   62 #include <sys/malloc.h>
   63 #include <sys/module.h>
   64 #include <sys/sysent.h>
   65 #include <sys/syscall.h>
   66 #include <sys/sysproto.h>
   67 
   68 #include <vm/vm.h>
   69 #include <vm/vm_object.h>
   70 #include <vm/vm_extern.h>
   71 #include <vm/uma.h>
   72 
   73 #include <nfs/rpcv2.h>
   74 #include <nfs/nfsproto.h>
   75 #include <nfsserver/nfs.h>
   76 #include <nfs/xdr_subs.h>
   77 #include <nfsserver/nfsm_subs.h>
   78 
   79 #include <netinet/in.h>
   80 
   81 /*
   82  * Data items converted to xdr at startup, since they are constant
   83  * This is kinda hokey, but may save a little time doing byte swaps
   84  */
   85 u_int32_t nfsrv_nfs_xdrneg1;
   86 u_int32_t nfsrv_rpc_call, nfsrv_rpc_vers, nfsrv_rpc_reply,
   87         nfsrv_rpc_msgdenied, nfsrv_rpc_autherr,
   88         nfsrv_rpc_mismatch, nfsrv_rpc_auth_unix, nfsrv_rpc_msgaccepted;
   89 u_int32_t nfsrv_nfs_prog, nfsrv_nfs_true, nfsrv_nfs_false;
   90 
   91 /* And other global data */
   92 static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
   93                                  NFNON, NFCHR, NFNON };
   94 #define vtonfsv2_type(a)        txdr_unsigned(nfsv2_type[((int32_t)(a))])
   95 #define vtonfsv3_mode(m)        txdr_unsigned((m) & ALLPERMS)
   96 
   97 int nfsrv_ticks;
   98 
   99 struct nfssvc_sockhead nfssvc_sockhead;
  100 int nfssvc_sockhead_flag;
  101 struct nfsd_head nfsd_head;
  102 int nfsd_head_flag;
  103 
  104 static int nfs_prev_nfssvc_sy_narg;
  105 static sy_call_t *nfs_prev_nfssvc_sy_call;
  106 
  107 /*
  108  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
  109  */
  110 int nfsrv_nfsv3_procid[NFS_NPROCS] = {
  111         NFSPROC_NULL,
  112         NFSPROC_GETATTR,
  113         NFSPROC_SETATTR,
  114         NFSPROC_NOOP,
  115         NFSPROC_LOOKUP,
  116         NFSPROC_READLINK,
  117         NFSPROC_READ,
  118         NFSPROC_NOOP,
  119         NFSPROC_WRITE,
  120         NFSPROC_CREATE,
  121         NFSPROC_REMOVE,
  122         NFSPROC_RENAME,
  123         NFSPROC_LINK,
  124         NFSPROC_SYMLINK,
  125         NFSPROC_MKDIR,
  126         NFSPROC_RMDIR,
  127         NFSPROC_READDIR,
  128         NFSPROC_FSSTAT,
  129         NFSPROC_NOOP,
  130         NFSPROC_NOOP,
  131         NFSPROC_NOOP,
  132         NFSPROC_NOOP,
  133         NFSPROC_NOOP,
  134 };
  135 
  136 /*
  137  * and the reverse mapping from generic to Version 2 procedure numbers
  138  */
  139 int nfsrvv2_procid[NFS_NPROCS] = {
  140         NFSV2PROC_NULL,
  141         NFSV2PROC_GETATTR,
  142         NFSV2PROC_SETATTR,
  143         NFSV2PROC_LOOKUP,
  144         NFSV2PROC_NOOP,
  145         NFSV2PROC_READLINK,
  146         NFSV2PROC_READ,
  147         NFSV2PROC_WRITE,
  148         NFSV2PROC_CREATE,
  149         NFSV2PROC_MKDIR,
  150         NFSV2PROC_SYMLINK,
  151         NFSV2PROC_CREATE,
  152         NFSV2PROC_REMOVE,
  153         NFSV2PROC_RMDIR,
  154         NFSV2PROC_RENAME,
  155         NFSV2PROC_LINK,
  156         NFSV2PROC_READDIR,
  157         NFSV2PROC_NOOP,
  158         NFSV2PROC_STATFS,
  159         NFSV2PROC_NOOP,
  160         NFSV2PROC_NOOP,
  161         NFSV2PROC_NOOP,
  162         NFSV2PROC_NOOP,
  163 };
  164 
  165 /*
  166  * Maps errno values to nfs error numbers.
  167  * Use 0 (which gets converted to NFSERR_IO) as the catch all for ones not
  168  * specifically defined in RFC 1094.
  169  */
  170 static u_char nfsrv_v2errmap[ELAST] = {
  171   NFSERR_PERM,  NFSERR_NOENT,   0,              0,              0,      
  172   NFSERR_NXIO,  0,              0,              0,              0,      
  173   0,            0,              NFSERR_ACCES,   0,              0,      
  174   0,            NFSERR_EXIST,   0,              NFSERR_NODEV,   NFSERR_NOTDIR,
  175   NFSERR_ISDIR, 0,              0,              0,              0,      
  176   0,            NFSERR_FBIG,    NFSERR_NOSPC,   0,              NFSERR_ROFS,
  177   0,            0,              0,              0,              0,      
  178   0,            0,              0,              0,              0,      
  179   0,            0,              0,              0,              0,      
  180   0,            0,              0,              0,              0,      
  181   0,            0,              0,              0,              0,      
  182   0,            0,              0,              0,              0,      
  183   0,            0,              NFSERR_NAMETOL, 0,              0,      
  184   NFSERR_NOTEMPTY, 0,           0,              NFSERR_DQUOT,   NFSERR_STALE,
  185   0
  186 };
  187 
  188 /*
  189  * Maps errno values to nfs error numbers.
  190  * Although it is not obvious whether or not NFS clients really care if
  191  * a returned error value is in the specified list for the procedure, the
  192  * safest thing to do is filter them appropriately. For Version 2, the
  193  * X/Open XNFS document is the only specification that defines error values
  194  * for each RPC (The RFC simply lists all possible error values for all RPCs),
  195  * so I have decided to not do this for Version 2.
  196  * The first entry is the default error return and the rest are the valid
  197  * errors for that RPC in increasing numeric order.
  198  */
  199 static short nfsv3err_null[] = {
  200         0,
  201         0,
  202 };
  203 
  204 static short nfsv3err_getattr[] = {
  205         NFSERR_IO,
  206         NFSERR_IO,
  207         NFSERR_STALE,
  208         NFSERR_BADHANDLE,
  209         NFSERR_SERVERFAULT,
  210         0,
  211 };
  212 
  213 static short nfsv3err_setattr[] = {
  214         NFSERR_IO,
  215         NFSERR_PERM,
  216         NFSERR_IO,
  217         NFSERR_ACCES,
  218         NFSERR_INVAL,
  219         NFSERR_NOSPC,
  220         NFSERR_ROFS,
  221         NFSERR_DQUOT,
  222         NFSERR_STALE,
  223         NFSERR_BADHANDLE,
  224         NFSERR_NOT_SYNC,
  225         NFSERR_SERVERFAULT,
  226         0,
  227 };
  228 
  229 static short nfsv3err_lookup[] = {
  230         NFSERR_IO,
  231         NFSERR_NOENT,
  232         NFSERR_IO,
  233         NFSERR_ACCES,
  234         NFSERR_NOTDIR,
  235         NFSERR_NAMETOL,
  236         NFSERR_STALE,
  237         NFSERR_BADHANDLE,
  238         NFSERR_SERVERFAULT,
  239         0,
  240 };
  241 
  242 static short nfsv3err_access[] = {
  243         NFSERR_IO,
  244         NFSERR_IO,
  245         NFSERR_STALE,
  246         NFSERR_BADHANDLE,
  247         NFSERR_SERVERFAULT,
  248         0,
  249 };
  250 
  251 static short nfsv3err_readlink[] = {
  252         NFSERR_IO,
  253         NFSERR_IO,
  254         NFSERR_ACCES,
  255         NFSERR_INVAL,
  256         NFSERR_STALE,
  257         NFSERR_BADHANDLE,
  258         NFSERR_NOTSUPP,
  259         NFSERR_SERVERFAULT,
  260         0,
  261 };
  262 
  263 static short nfsv3err_read[] = {
  264         NFSERR_IO,
  265         NFSERR_IO,
  266         NFSERR_NXIO,
  267         NFSERR_ACCES,
  268         NFSERR_INVAL,
  269         NFSERR_STALE,
  270         NFSERR_BADHANDLE,
  271         NFSERR_SERVERFAULT,
  272         0,
  273 };
  274 
  275 static short nfsv3err_write[] = {
  276         NFSERR_IO,
  277         NFSERR_IO,
  278         NFSERR_ACCES,
  279         NFSERR_INVAL,
  280         NFSERR_FBIG,
  281         NFSERR_NOSPC,
  282         NFSERR_ROFS,
  283         NFSERR_DQUOT,
  284         NFSERR_STALE,
  285         NFSERR_BADHANDLE,
  286         NFSERR_SERVERFAULT,
  287         0,
  288 };
  289 
  290 static short nfsv3err_create[] = {
  291         NFSERR_IO,
  292         NFSERR_IO,
  293         NFSERR_ACCES,
  294         NFSERR_EXIST,
  295         NFSERR_NOTDIR,
  296         NFSERR_NOSPC,
  297         NFSERR_ROFS,
  298         NFSERR_NAMETOL,
  299         NFSERR_DQUOT,
  300         NFSERR_STALE,
  301         NFSERR_BADHANDLE,
  302         NFSERR_NOTSUPP,
  303         NFSERR_SERVERFAULT,
  304         0,
  305 };
  306 
  307 static short nfsv3err_mkdir[] = {
  308         NFSERR_IO,
  309         NFSERR_IO,
  310         NFSERR_ACCES,
  311         NFSERR_EXIST,
  312         NFSERR_NOTDIR,
  313         NFSERR_NOSPC,
  314         NFSERR_ROFS,
  315         NFSERR_NAMETOL,
  316         NFSERR_DQUOT,
  317         NFSERR_STALE,
  318         NFSERR_BADHANDLE,
  319         NFSERR_NOTSUPP,
  320         NFSERR_SERVERFAULT,
  321         0,
  322 };
  323 
  324 static short nfsv3err_symlink[] = {
  325         NFSERR_IO,
  326         NFSERR_IO,
  327         NFSERR_ACCES,
  328         NFSERR_EXIST,
  329         NFSERR_NOTDIR,
  330         NFSERR_NOSPC,
  331         NFSERR_ROFS,
  332         NFSERR_NAMETOL,
  333         NFSERR_DQUOT,
  334         NFSERR_STALE,
  335         NFSERR_BADHANDLE,
  336         NFSERR_NOTSUPP,
  337         NFSERR_SERVERFAULT,
  338         0,
  339 };
  340 
  341 static short nfsv3err_mknod[] = {
  342         NFSERR_IO,
  343         NFSERR_IO,
  344         NFSERR_ACCES,
  345         NFSERR_EXIST,
  346         NFSERR_NOTDIR,
  347         NFSERR_NOSPC,
  348         NFSERR_ROFS,
  349         NFSERR_NAMETOL,
  350         NFSERR_DQUOT,
  351         NFSERR_STALE,
  352         NFSERR_BADHANDLE,
  353         NFSERR_NOTSUPP,
  354         NFSERR_SERVERFAULT,
  355         NFSERR_BADTYPE,
  356         0,
  357 };
  358 
  359 static short nfsv3err_remove[] = {
  360         NFSERR_IO,
  361         NFSERR_NOENT,
  362         NFSERR_IO,
  363         NFSERR_ACCES,
  364         NFSERR_NOTDIR,
  365         NFSERR_ROFS,
  366         NFSERR_NAMETOL,
  367         NFSERR_STALE,
  368         NFSERR_BADHANDLE,
  369         NFSERR_SERVERFAULT,
  370         0,
  371 };
  372 
  373 static short nfsv3err_rmdir[] = {
  374         NFSERR_IO,
  375         NFSERR_NOENT,
  376         NFSERR_IO,
  377         NFSERR_ACCES,
  378         NFSERR_EXIST,
  379         NFSERR_NOTDIR,
  380         NFSERR_INVAL,
  381         NFSERR_ROFS,
  382         NFSERR_NAMETOL,
  383         NFSERR_NOTEMPTY,
  384         NFSERR_STALE,
  385         NFSERR_BADHANDLE,
  386         NFSERR_NOTSUPP,
  387         NFSERR_SERVERFAULT,
  388         0,
  389 };
  390 
  391 static short nfsv3err_rename[] = {
  392         NFSERR_IO,
  393         NFSERR_NOENT,
  394         NFSERR_IO,
  395         NFSERR_ACCES,
  396         NFSERR_EXIST,
  397         NFSERR_XDEV,
  398         NFSERR_NOTDIR,
  399         NFSERR_ISDIR,
  400         NFSERR_INVAL,
  401         NFSERR_NOSPC,
  402         NFSERR_ROFS,
  403         NFSERR_MLINK,
  404         NFSERR_NAMETOL,
  405         NFSERR_NOTEMPTY,
  406         NFSERR_DQUOT,
  407         NFSERR_STALE,
  408         NFSERR_BADHANDLE,
  409         NFSERR_NOTSUPP,
  410         NFSERR_SERVERFAULT,
  411         0,
  412 };
  413 
  414 static short nfsv3err_link[] = {
  415         NFSERR_IO,
  416         NFSERR_IO,
  417         NFSERR_ACCES,
  418         NFSERR_EXIST,
  419         NFSERR_XDEV,
  420         NFSERR_NOTDIR,
  421         NFSERR_INVAL,
  422         NFSERR_NOSPC,
  423         NFSERR_ROFS,
  424         NFSERR_MLINK,
  425         NFSERR_NAMETOL,
  426         NFSERR_DQUOT,
  427         NFSERR_STALE,
  428         NFSERR_BADHANDLE,
  429         NFSERR_NOTSUPP,
  430         NFSERR_SERVERFAULT,
  431         0,
  432 };
  433 
  434 static short nfsv3err_readdir[] = {
  435         NFSERR_IO,
  436         NFSERR_IO,
  437         NFSERR_ACCES,
  438         NFSERR_NOTDIR,
  439         NFSERR_STALE,
  440         NFSERR_BADHANDLE,
  441         NFSERR_BAD_COOKIE,
  442         NFSERR_TOOSMALL,
  443         NFSERR_SERVERFAULT,
  444         0,
  445 };
  446 
  447 static short nfsv3err_readdirplus[] = {
  448         NFSERR_IO,
  449         NFSERR_IO,
  450         NFSERR_ACCES,
  451         NFSERR_NOTDIR,
  452         NFSERR_STALE,
  453         NFSERR_BADHANDLE,
  454         NFSERR_BAD_COOKIE,
  455         NFSERR_NOTSUPP,
  456         NFSERR_TOOSMALL,
  457         NFSERR_SERVERFAULT,
  458         0,
  459 };
  460 
  461 static short nfsv3err_fsstat[] = {
  462         NFSERR_IO,
  463         NFSERR_IO,
  464         NFSERR_STALE,
  465         NFSERR_BADHANDLE,
  466         NFSERR_SERVERFAULT,
  467         0,
  468 };
  469 
  470 static short nfsv3err_fsinfo[] = {
  471         NFSERR_STALE,
  472         NFSERR_STALE,
  473         NFSERR_BADHANDLE,
  474         NFSERR_SERVERFAULT,
  475         0,
  476 };
  477 
  478 static short nfsv3err_pathconf[] = {
  479         NFSERR_STALE,
  480         NFSERR_STALE,
  481         NFSERR_BADHANDLE,
  482         NFSERR_SERVERFAULT,
  483         0,
  484 };
  485 
  486 static short nfsv3err_commit[] = {
  487         NFSERR_IO,
  488         NFSERR_IO,
  489         NFSERR_STALE,
  490         NFSERR_BADHANDLE,
  491         NFSERR_SERVERFAULT,
  492         0,
  493 };
  494 
  495 static short *nfsrv_v3errmap[] = {
  496         nfsv3err_null,
  497         nfsv3err_getattr,
  498         nfsv3err_setattr,
  499         nfsv3err_lookup,
  500         nfsv3err_access,
  501         nfsv3err_readlink,
  502         nfsv3err_read,
  503         nfsv3err_write,
  504         nfsv3err_create,
  505         nfsv3err_mkdir,
  506         nfsv3err_symlink,
  507         nfsv3err_mknod,
  508         nfsv3err_remove,
  509         nfsv3err_rmdir,
  510         nfsv3err_rename,
  511         nfsv3err_link,
  512         nfsv3err_readdir,
  513         nfsv3err_readdirplus,
  514         nfsv3err_fsstat,
  515         nfsv3err_fsinfo,
  516         nfsv3err_pathconf,
  517         nfsv3err_commit,
  518 };
  519 
  520 /*
  521  * Called once to initialize data structures...
  522  */
  523 static int
  524 nfsrv_modevent(module_t mod, int type, void *data)
  525 {
  526 
  527         switch (type) {
  528         case MOD_LOAD:
  529                 nfsrv_rpc_vers = txdr_unsigned(RPC_VER2);
  530                 nfsrv_rpc_call = txdr_unsigned(RPC_CALL);
  531                 nfsrv_rpc_reply = txdr_unsigned(RPC_REPLY);
  532                 nfsrv_rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
  533                 nfsrv_rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
  534                 nfsrv_rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
  535                 nfsrv_rpc_autherr = txdr_unsigned(RPC_AUTHERR);
  536                 nfsrv_rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
  537                 nfsrv_nfs_prog = txdr_unsigned(NFS_PROG);
  538                 nfsrv_nfs_true = txdr_unsigned(TRUE);
  539                 nfsrv_nfs_false = txdr_unsigned(FALSE);
  540                 nfsrv_nfs_xdrneg1 = txdr_unsigned(-1);
  541                 nfsrv_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
  542                 if (nfsrv_ticks < 1)
  543                         nfsrv_ticks = 1;
  544 
  545                 nfsrv_init(0);          /* Init server data structures */
  546                 nfsrv_initcache();      /* Init the server request cache */
  547 
  548                 nfsrv_timer(0);
  549 
  550                 nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
  551                 sysent[SYS_nfssvc].sy_narg = 2;
  552                 nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
  553                 sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
  554                 break;
  555 
  556                 case MOD_UNLOAD:
  557 
  558                 untimeout(nfsrv_timer, (void *)NULL, nfsrv_timer_handle);
  559                 sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
  560                 sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
  561                 break;
  562         }
  563         return 0;
  564 }
  565 static moduledata_t nfsserver_mod = {
  566         "nfsserver",
  567         nfsrv_modevent,
  568         NULL,
  569 };
  570 DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
  571 
  572 /* So that loader and kldload(2) can find us, wherever we are.. */
  573 MODULE_VERSION(nfsserver, 1);
  574 
  575 /*
  576  * Set up nameidata for a lookup() call and do it.
  577  *
  578  * If pubflag is set, this call is done for a lookup operation on the
  579  * public filehandle. In that case we allow crossing mountpoints and
  580  * absolute pathnames. However, the caller is expected to check that
  581  * the lookup result is within the public fs, and deny access if
  582  * it is not.
  583  *
  584  * nfs_namei() clears out garbage fields that namei() might leave garbage.
  585  * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
  586  * error occurs but the parent was not requested.
  587  *
  588  * dirp may be set whether an error is returned or not, and must be
  589  * released by the caller.
  590  */
  591 int
  592 nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
  593     struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp,
  594     caddr_t *dposp, struct vnode **retdirp, int v3, struct vattr *retdirattrp,
  595     int *retdirattr_retp, struct thread *td, int pubflag)
  596 {
  597         int i, rem;
  598         struct mbuf *md;
  599         char *fromcp, *tocp, *cp;
  600         struct iovec aiov;
  601         struct uio auio;
  602         struct vnode *dp;
  603         int error, rdonly, linklen;
  604         struct componentname *cnp = &ndp->ni_cnd;
  605         int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0;
  606 
  607         *retdirp = NULL;
  608         cnp->cn_flags |= NOMACCHECK;
  609         cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
  610 
  611         /*
  612          * Copy the name from the mbuf list to ndp->ni_pnbuf
  613          * and set the various ndp fields appropriately.
  614          */
  615         fromcp = *dposp;
  616         tocp = cnp->cn_pnbuf;
  617         md = *mdp;
  618         rem = mtod(md, caddr_t) + md->m_len - fromcp;
  619         for (i = 0; i < len; i++) {
  620                 while (rem == 0) {
  621                         md = md->m_next;
  622                         if (md == NULL) {
  623                                 error = EBADRPC;
  624                                 goto out;
  625                         }
  626                         fromcp = mtod(md, caddr_t);
  627                         rem = md->m_len;
  628                 }
  629                 if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
  630                         error = EACCES;
  631                         goto out;
  632                 }
  633                 *tocp++ = *fromcp++;
  634                 rem--;
  635         }
  636         *tocp = '\0';
  637         *mdp = md;
  638         *dposp = fromcp;
  639         len = nfsm_rndup(len)-len;
  640         if (len > 0) {
  641                 if (rem >= len)
  642                         *dposp += len;
  643                 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
  644                         goto out;
  645         }
  646 
  647         /*
  648          * Extract and set starting directory.
  649          */
  650         error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
  651             nam, &rdonly, pubflag);
  652         if (error)
  653                 goto out;
  654         if (dp->v_type != VDIR) {
  655                 vrele(dp);
  656                 error = ENOTDIR;
  657                 goto out;
  658         }
  659 
  660         if (rdonly)
  661                 cnp->cn_flags |= RDONLY;
  662 
  663         /*
  664          * Set return directory.  Reference to dp is implicitly transfered
  665          * to the returned pointer
  666          */
  667         *retdirp = dp;
  668         if (v3) {
  669                 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
  670                 *retdirattr_retp = VOP_GETATTR(dp, retdirattrp,
  671                         ndp->ni_cnd.cn_cred, td);
  672                 VOP_UNLOCK(dp, 0, td);
  673         }
  674 
  675         if (pubflag) {
  676                 /*
  677                  * Oh joy. For WebNFS, handle those pesky '%' escapes,
  678                  * and the 'native path' indicator.
  679                  */
  680                 cp = uma_zalloc(namei_zone, M_WAITOK);
  681                 fromcp = cnp->cn_pnbuf;
  682                 tocp = cp;
  683                 if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
  684                         switch ((unsigned char)*fromcp) {
  685                         case WEBNFS_NATIVE_CHAR:
  686                                 /*
  687                                  * 'Native' path for us is the same
  688                                  * as a path according to the NFS spec,
  689                                  * just skip the escape char.
  690                                  */
  691                                 fromcp++;
  692                                 break;
  693                         /*
  694                          * More may be added in the future, range 0x80-0xff
  695                          */
  696                         default:
  697                                 error = EIO;
  698                                 uma_zfree(namei_zone, cp);
  699                                 goto out;
  700                         }
  701                 }
  702                 /*
  703                  * Translate the '%' escapes, URL-style.
  704                  */
  705                 while (*fromcp != '\0') {
  706                         if (*fromcp == WEBNFS_ESC_CHAR) {
  707                                 if (fromcp[1] != '\0' && fromcp[2] != '\0') {
  708                                         fromcp++;
  709                                         *tocp++ = HEXSTRTOI(fromcp);
  710                                         fromcp += 2;
  711                                         continue;
  712                                 } else {
  713                                         error = ENOENT;
  714                                         uma_zfree(namei_zone, cp);
  715                                         goto out;
  716                                 }
  717                         } else
  718                                 *tocp++ = *fromcp++;
  719                 }
  720                 *tocp = '\0';
  721                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  722                 cnp->cn_pnbuf = cp;
  723         }
  724 
  725         ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
  726         ndp->ni_segflg = UIO_SYSSPACE;
  727 
  728         if (pubflag) {
  729                 ndp->ni_rootdir = rootvnode;
  730                 ndp->ni_loopcnt = 0;
  731                 if (cnp->cn_pnbuf[0] == '/')
  732                         dp = rootvnode;
  733         } else {
  734                 cnp->cn_flags |= NOCROSSMOUNT;
  735         }
  736 
  737         /*
  738          * Initialize for scan, set ni_startdir and bump ref on dp again
  739          * becuase lookup() will dereference ni_startdir.
  740          */
  741 
  742         cnp->cn_thread = td;
  743         VREF(dp);
  744         ndp->ni_startdir = dp;
  745 
  746         if (!lockleaf)
  747                 cnp->cn_flags |= LOCKLEAF;
  748         for (;;) {
  749                 cnp->cn_nameptr = cnp->cn_pnbuf;
  750                 /*
  751                  * Call lookup() to do the real work.  If an error occurs,
  752                  * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
  753                  * we do not have to dereference anything before returning.
  754                  * In either case ni_startdir will be dereferenced and NULLed
  755                  * out.
  756                  */
  757                 error = lookup(ndp);
  758                 if (error)
  759                         break;
  760 
  761                 /*
  762                  * Check for encountering a symbolic link.  Trivial
  763                  * termination occurs if no symlink encountered.
  764                  * Note: zfree is safe because error is 0, so we will
  765                  * not zfree it again when we break.
  766                  */
  767                 if ((cnp->cn_flags & ISSYMLINK) == 0) {
  768                         nfsrv_object_create(ndp->ni_vp);
  769                         if (cnp->cn_flags & (SAVENAME | SAVESTART))
  770                                 cnp->cn_flags |= HASBUF;
  771                         else
  772                                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  773                         if (ndp->ni_vp && !lockleaf)
  774                                 VOP_UNLOCK(ndp->ni_vp, 0, td);
  775                         break;
  776                 }
  777 
  778                 /*
  779                  * Validate symlink
  780                  */
  781                 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
  782                         VOP_UNLOCK(ndp->ni_dvp, 0, td);
  783                 if (!pubflag) {
  784                         error = EINVAL;
  785                         goto badlink2;
  786                 }
  787 
  788                 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
  789                         error = ELOOP;
  790                         goto badlink2;
  791                 }
  792                 if (ndp->ni_pathlen > 1)
  793                         cp = uma_zalloc(namei_zone, M_WAITOK);
  794                 else
  795                         cp = cnp->cn_pnbuf;
  796                 aiov.iov_base = cp;
  797                 aiov.iov_len = MAXPATHLEN;
  798                 auio.uio_iov = &aiov;
  799                 auio.uio_iovcnt = 1;
  800                 auio.uio_offset = 0;
  801                 auio.uio_rw = UIO_READ;
  802                 auio.uio_segflg = UIO_SYSSPACE;
  803                 auio.uio_td = NULL;
  804                 auio.uio_resid = MAXPATHLEN;
  805                 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
  806                 if (error) {
  807                 badlink1:
  808                         if (ndp->ni_pathlen > 1)
  809                                 uma_zfree(namei_zone, cp);
  810                 badlink2:
  811                         vrele(ndp->ni_dvp);
  812                         vput(ndp->ni_vp);
  813                         break;
  814                 }
  815                 linklen = MAXPATHLEN - auio.uio_resid;
  816                 if (linklen == 0) {
  817                         error = ENOENT;
  818                         goto badlink1;
  819                 }
  820                 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
  821                         error = ENAMETOOLONG;
  822                         goto badlink1;
  823                 }
  824 
  825                 /*
  826                  * Adjust or replace path
  827                  */
  828                 if (ndp->ni_pathlen > 1) {
  829                         bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
  830                         uma_zfree(namei_zone, cnp->cn_pnbuf);
  831                         cnp->cn_pnbuf = cp;
  832                 } else
  833                         cnp->cn_pnbuf[linklen] = '\0';
  834                 ndp->ni_pathlen += linklen;
  835 
  836                 /*
  837                  * Cleanup refs for next loop and check if root directory
  838                  * should replace current directory.  Normally ni_dvp
  839                  * becomes the new base directory and is cleaned up when
  840                  * we loop.  Explicitly null pointers after invalidation
  841                  * to clarify operation.
  842                  */
  843                 vput(ndp->ni_vp);
  844                 ndp->ni_vp = NULL;
  845 
  846                 if (cnp->cn_pnbuf[0] == '/') {
  847                         vrele(ndp->ni_dvp);
  848                         ndp->ni_dvp = ndp->ni_rootdir;
  849                         VREF(ndp->ni_dvp);
  850                 }
  851                 ndp->ni_startdir = ndp->ni_dvp;
  852                 ndp->ni_dvp = NULL;
  853         }
  854         if (!lockleaf)
  855                 cnp->cn_flags &= ~LOCKLEAF;
  856 
  857         /*
  858          * nfs_namei() guarentees that fields will not contain garbage
  859          * whether an error occurs or not.  This allows the caller to track
  860          * cleanup state trivially.
  861          */
  862 out:
  863         if (error) {
  864                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  865                 ndp->ni_vp = NULL;
  866                 ndp->ni_dvp = NULL;
  867                 ndp->ni_startdir = NULL;
  868                 cnp->cn_flags &= ~HASBUF;
  869         } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
  870                 ndp->ni_dvp = NULL;
  871         }
  872         return (error);
  873 }
  874 
  875 /*
  876  * A fiddled version of m_adj() that ensures null fill to a long
  877  * boundary and only trims off the back end
  878  */
  879 void
  880 nfsm_adj(struct mbuf *mp, int len, int nul)
  881 {
  882         struct mbuf *m;
  883         int count, i;
  884         char *cp;
  885 
  886         /*
  887          * Trim from tail.  Scan the mbuf chain,
  888          * calculating its length and finding the last mbuf.
  889          * If the adjustment only affects this mbuf, then just
  890          * adjust and return.  Otherwise, rescan and truncate
  891          * after the remaining size.
  892          */
  893         count = 0;
  894         m = mp;
  895         for (;;) {
  896                 count += m->m_len;
  897                 if (m->m_next == NULL)
  898                         break;
  899                 m = m->m_next;
  900         }
  901         if (m->m_len > len) {
  902                 m->m_len -= len;
  903                 if (nul > 0) {
  904                         cp = mtod(m, caddr_t)+m->m_len-nul;
  905                         for (i = 0; i < nul; i++)
  906                                 *cp++ = '\0';
  907                 }
  908                 return;
  909         }
  910         count -= len;
  911         if (count < 0)
  912                 count = 0;
  913         /*
  914          * Correct length for chain is "count".
  915          * Find the mbuf with last data, adjust its length,
  916          * and toss data from remaining mbufs on chain.
  917          */
  918         for (m = mp; m; m = m->m_next) {
  919                 if (m->m_len >= count) {
  920                         m->m_len = count;
  921                         if (nul > 0) {
  922                                 cp = mtod(m, caddr_t)+m->m_len-nul;
  923                                 for (i = 0; i < nul; i++)
  924                                         *cp++ = '\0';
  925                         }
  926                         break;
  927                 }
  928                 count -= m->m_len;
  929         }
  930         for (m = m->m_next;m;m = m->m_next)
  931                 m->m_len = 0;
  932 }
  933 
  934 /*
  935  * Make these functions instead of macros, so that the kernel text size
  936  * doesn't get too big...
  937  */
  938 void
  939 nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
  940     struct vattr *before_vap, int after_ret, struct vattr *after_vap,
  941     struct mbuf **mbp, char **bposp)
  942 {
  943         struct mbuf *mb = *mbp;
  944         char *bpos = *bposp;
  945         u_int32_t *tl;
  946 
  947         if (before_ret) {
  948                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  949                 *tl = nfsrv_nfs_false;
  950         } else {
  951                 tl = nfsm_build(u_int32_t *, 7 * NFSX_UNSIGNED);
  952                 *tl++ = nfsrv_nfs_true;
  953                 txdr_hyper(before_vap->va_size, tl);
  954                 tl += 2;
  955                 txdr_nfsv3time(&(before_vap->va_mtime), tl);
  956                 tl += 2;
  957                 txdr_nfsv3time(&(before_vap->va_ctime), tl);
  958         }
  959         *bposp = bpos;
  960         *mbp = mb;
  961         nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
  962 }
  963 
  964 void
  965 nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
  966     struct vattr *after_vap, struct mbuf **mbp, char **bposp)
  967 {
  968         struct mbuf *mb = *mbp;
  969         char *bpos = *bposp;
  970         u_int32_t *tl;
  971         struct nfs_fattr *fp;
  972 
  973         if (after_ret) {
  974                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  975                 *tl = nfsrv_nfs_false;
  976         } else {
  977                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
  978                 *tl++ = nfsrv_nfs_true;
  979                 fp = (struct nfs_fattr *)tl;
  980                 nfsm_srvfattr(nfsd, after_vap, fp);
  981         }
  982         *mbp = mb;
  983         *bposp = bpos;
  984 }
  985 
  986 void
  987 nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
  988     struct nfs_fattr *fp)
  989 {
  990 
  991         fp->fa_nlink = txdr_unsigned(vap->va_nlink);
  992         fp->fa_uid = txdr_unsigned(vap->va_uid);
  993         fp->fa_gid = txdr_unsigned(vap->va_gid);
  994         if (nfsd->nd_flag & ND_NFSV3) {
  995                 fp->fa_type = vtonfsv3_type(vap->va_type);
  996                 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
  997                 txdr_hyper(vap->va_size, &fp->fa3_size);
  998                 txdr_hyper(vap->va_bytes, &fp->fa3_used);
  999                 fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
 1000                 fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
 1001                 fp->fa3_fsid.nfsuquad[0] = 0;
 1002                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
 1003                 fp->fa3_fileid.nfsuquad[0] = 0;
 1004                 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
 1005                 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
 1006                 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
 1007                 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
 1008         } else {
 1009                 fp->fa_type = vtonfsv2_type(vap->va_type);
 1010                 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1011                 fp->fa2_size = txdr_unsigned(vap->va_size);
 1012                 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
 1013                 if (vap->va_type == VFIFO)
 1014                         fp->fa2_rdev = 0xffffffff;
 1015                 else
 1016                         fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
 1017                 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
 1018                 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
 1019                 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
 1020                 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
 1021                 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
 1022                 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
 1023         }
 1024 }
 1025 
 1026 /*
 1027  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
 1028  *      - look up fsid in mount list (if not found ret error)
 1029  *      - get vp and export rights by calling VFS_FHTOVP()
 1030  *      - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
 1031  *      - if not lockflag unlock it with VOP_UNLOCK()
 1032  */
 1033 int
 1034 nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
 1035     struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
 1036     int *rdonlyp, int pubflag)
 1037 {
 1038         struct thread *td = curthread; /* XXX */
 1039         struct mount *mp;
 1040         int i;
 1041         struct ucred *credanon;
 1042         int error, exflags;
 1043 #ifdef MNT_EXNORESPORT          /* XXX needs mountd and /etc/exports help yet */
 1044         struct sockaddr_int *saddr;
 1045 #endif
 1046 
 1047         *vpp = NULL;
 1048 
 1049         if (nfs_ispublicfh(fhp)) {
 1050                 if (!pubflag || !nfs_pub.np_valid)
 1051                         return (ESTALE);
 1052                 fhp = &nfs_pub.np_handle;
 1053         }
 1054 
 1055         mp = vfs_getvfs(&fhp->fh_fsid);
 1056         if (!mp)
 1057                 return (ESTALE);
 1058         error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
 1059         if (error)
 1060                 return (error);
 1061         error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
 1062         if (error)
 1063                 return (error);
 1064 #ifdef MNT_EXNORESPORT
 1065         if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
 1066                 saddr = (struct sockaddr_in *)nam;
 1067                 if ((saddr->sin_family == AF_INET ||
 1068                      saddr->sin_family == AF_INET6) &&
 1069         /* same code for INET and INET6: sin*_port at same offet */
 1070                     ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
 1071                         vput(*vpp);
 1072                         *vpp = NULL;
 1073                         return (NFSERR_AUTHERR | AUTH_TOOWEAK);
 1074                 }
 1075         }
 1076 #endif
 1077         /*
 1078          * Check/setup credentials.
 1079          */
 1080         if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
 1081                 cred->cr_uid = credanon->cr_uid;
 1082                 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
 1083                         cred->cr_groups[i] = credanon->cr_groups[i];
 1084                 cred->cr_ngroups = i;
 1085         }
 1086         if (exflags & MNT_EXRDONLY)
 1087                 *rdonlyp = 1;
 1088         else
 1089                 *rdonlyp = 0;
 1090 
 1091         nfsrv_object_create(*vpp);
 1092 
 1093         if (!lockflag)
 1094                 VOP_UNLOCK(*vpp, 0, td);
 1095         return (0);
 1096 }
 1097 
 1098 
 1099 /*
 1100  * WebNFS: check if a filehandle is a public filehandle. For v3, this
 1101  * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
 1102  * transformed this to all zeroes in both cases, so check for it.
 1103  */
 1104 int
 1105 nfs_ispublicfh(fhandle_t *fhp)
 1106 {
 1107         char *cp = (char *)fhp;
 1108         int i;
 1109 
 1110         for (i = 0; i < NFSX_V3FH; i++)
 1111                 if (*cp++ != 0)
 1112                         return (FALSE);
 1113         return (TRUE);
 1114 }
 1115 
 1116 /*
 1117  * This function compares two net addresses by family and returns TRUE
 1118  * if they are the same host.
 1119  * If there is any doubt, return FALSE.
 1120  * The AF_INET family is handled as a special case so that address mbufs
 1121  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
 1122  */
 1123 int
 1124 netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
 1125 {
 1126         struct sockaddr_in *inetaddr;
 1127 
 1128         switch (family) {
 1129         case AF_INET:
 1130                 inetaddr = (struct sockaddr_in *)nam;
 1131                 if (inetaddr->sin_family == AF_INET &&
 1132                     inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
 1133                         return (1);
 1134                 break;
 1135 #ifdef INET6
 1136         case AF_INET6:
 1137         {
 1138                 register struct sockaddr_in6 *inet6addr1, *inet6addr2;
 1139 
 1140                 inet6addr1 = (struct sockaddr_in6 *)nam;
 1141                 inet6addr2 = (struct sockaddr_in6 *)haddr->had_nam;
 1142         /* XXX - should test sin6_scope_id ? */
 1143                 if (inet6addr1->sin6_family == AF_INET6 &&
 1144                     IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
 1145                                        &inet6addr2->sin6_addr))
 1146                         return (1);
 1147                 break;
 1148         }
 1149 #endif
 1150         default:
 1151                 break;
 1152         };
 1153         return (0);
 1154 }
 1155 
 1156 /*
 1157  * Map errnos to NFS error numbers. For Version 3 also filter out error
 1158  * numbers not specified for the associated procedure.
 1159  */
 1160 int
 1161 nfsrv_errmap(struct nfsrv_descript *nd, int err)
 1162 {
 1163         short *defaulterrp, *errp;
 1164         int e;
 1165 
 1166         if (nd->nd_flag & ND_NFSV3) {
 1167             if (nd->nd_procnum <= NFSPROC_COMMIT) {
 1168                 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
 1169                 while (*++errp) {
 1170                         if (*errp == err)
 1171                                 return (err);
 1172                         else if (*errp > err)
 1173                                 break;
 1174                 }
 1175                 return ((int)*defaulterrp);
 1176             } else
 1177                 return (err & 0xffff);
 1178         }
 1179         e = 0;
 1180         if (err <= ELAST)
 1181                 e = nfsrv_v2errmap[err - 1];
 1182         if (e != 0)
 1183                 return (e);
 1184         return (NFSERR_IO);
 1185 }
 1186 
 1187 int
 1188 nfsrv_object_create(struct vnode *vp)
 1189 {
 1190 
 1191         if (vp == NULL || vp->v_type != VREG)
 1192                 return (1);
 1193         return (vfs_object_create(vp, curthread, curthread->td_ucred));
 1194 }
 1195 
 1196 /*
 1197  * Sort the group list in increasing numerical order.
 1198  * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
 1199  *  that used to be here.)
 1200  */
 1201 void
 1202 nfsrvw_sort(gid_t *list, int num)
 1203 {
 1204         int i, j;
 1205         gid_t v;
 1206 
 1207         /* Insertion sort. */
 1208         for (i = 1; i < num; i++) {
 1209                 v = list[i];
 1210                 /* find correct slot for value v, moving others up */
 1211                 for (j = i; --j >= 0 && v < list[j];)
 1212                         list[j + 1] = list[j];
 1213                 list[j + 1] = v;
 1214         }
 1215 }
 1216 
 1217 /*
 1218  * copy credentials making sure that the result can be compared with bcmp().
 1219  */
 1220 void
 1221 nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
 1222 {
 1223         int i;
 1224 
 1225         bzero((caddr_t)outcred, sizeof (struct ucred));
 1226         outcred->cr_ref = 1;
 1227         outcred->cr_uid = incred->cr_uid;
 1228         outcred->cr_ngroups = incred->cr_ngroups;
 1229         for (i = 0; i < incred->cr_ngroups; i++)
 1230                 outcred->cr_groups[i] = incred->cr_groups[i];
 1231         nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
 1232 }
 1233 
 1234 /*
 1235  * Helper functions for macros.
 1236  */
 1237 
 1238 void
 1239 nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos)
 1240 {
 1241         u_int32_t *tl;
 1242 
 1243         if (v3) {
 1244                 tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
 1245                 *tl++ = txdr_unsigned(NFSX_V3FH);
 1246                 bcopy(f, tl, NFSX_V3FH);
 1247         } else {
 1248                 tl = nfsm_build_xx(NFSX_V2FH, mb, bpos);
 1249                 bcopy(f, tl, NFSX_V2FH);
 1250         }
 1251 }
 1252 
 1253 void
 1254 nfsm_srvpostop_fh_xx(fhandle_t *f, struct mbuf **mb, caddr_t *bpos)
 1255 {
 1256         u_int32_t *tl;
 1257 
 1258         tl = nfsm_build_xx(2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
 1259         *tl++ = nfsrv_nfs_true;
 1260         *tl++ = txdr_unsigned(NFSX_V3FH);
 1261         bcopy(f, tl, NFSX_V3FH);
 1262 }
 1263 
 1264 int
 1265 nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
 1266 {
 1267         u_int32_t *tl;
 1268 
 1269         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1270         if (tl == NULL)
 1271                 return EBADRPC;
 1272         *s = fxdr_unsigned(int32_t, *tl);
 1273         if (*s > m || *s <= 0)
 1274                 return EBADRPC;
 1275         return 0;
 1276 }
 1277 
 1278 int
 1279 nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
 1280 {
 1281         u_int32_t *tl;
 1282 
 1283         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1284         if (tl == NULL)
 1285                 return EBADRPC;
 1286         *s = fxdr_unsigned(int32_t, *tl);
 1287         if (*s > m)
 1288                 return NFSERR_NAMETOL;
 1289         if (*s <= 0)
 1290                 return EBADRPC;
 1291         return 0;
 1292 }
 1293 
 1294 void
 1295 nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
 1296     char **bp, char **be, caddr_t bpos)
 1297 {
 1298         struct mbuf *nmp;
 1299 
 1300         if (*bp >= *be) {
 1301                 if (*mp == mb)
 1302                         (*mp)->m_len += *bp - bpos;
 1303                 MGET(nmp, M_TRYWAIT, MT_DATA);
 1304                 MCLGET(nmp, M_TRYWAIT);
 1305                 nmp->m_len = NFSMSIZ(nmp);
 1306                 (*mp)->m_next = nmp;
 1307                 *mp = nmp;
 1308                 *bp = mtod(*mp, caddr_t);
 1309                 *be = *bp + (*mp)->m_len;
 1310         }
 1311         *tl = (u_int32_t *)*bp;
 1312 }
 1313 
 1314 int
 1315 nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md,
 1316     caddr_t *dpos)
 1317 {
 1318         u_int32_t *tl;
 1319         int fhlen;
 1320 
 1321         if (nfsd->nd_flag & ND_NFSV3) {
 1322                 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1323                 if (tl == NULL)
 1324                         return EBADRPC;
 1325                 fhlen = fxdr_unsigned(int, *tl);
 1326                 if (fhlen != 0 && fhlen != NFSX_V3FH)
 1327                         return EBADRPC;
 1328         } else {
 1329                 fhlen = NFSX_V2FH;
 1330         }
 1331         if (fhlen != 0) {
 1332                 tl = nfsm_dissect_xx(fhlen, md, dpos);
 1333                 if (tl == NULL)
 1334                         return EBADRPC;
 1335                 bcopy((caddr_t)tl, (caddr_t)(f), fhlen);
 1336         } else {
 1337                 bzero((caddr_t)(f), NFSX_V3FH);
 1338         }
 1339         return 0;
 1340 }
 1341 
 1342 int
 1343 nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
 1344 {
 1345         u_int32_t *tl;
 1346 
 1347         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1348         if (tl == NULL)
 1349                 return EBADRPC;
 1350         if (*tl == nfsrv_nfs_true) {
 1351                 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1352                 if (tl == NULL)
 1353                         return EBADRPC;
 1354                 (a)->va_mode = nfstov_mode(*tl);
 1355         }
 1356         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1357         if (tl == NULL)
 1358                 return EBADRPC;
 1359         if (*tl == nfsrv_nfs_true) {
 1360                 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1361                 if (tl == NULL)
 1362                         return EBADRPC;
 1363                 (a)->va_uid = fxdr_unsigned(uid_t, *tl);
 1364         }
 1365         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1366         if (tl == NULL)
 1367                 return EBADRPC;
 1368         if (*tl == nfsrv_nfs_true) {
 1369                 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1370                 if (tl == NULL)
 1371                         return EBADRPC;
 1372                 (a)->va_gid = fxdr_unsigned(gid_t, *tl);
 1373         }
 1374         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1375         if (tl == NULL)
 1376                 return EBADRPC;
 1377         if (*tl == nfsrv_nfs_true) {
 1378                 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
 1379                 if (tl == NULL)
 1380                         return EBADRPC;
 1381                 (a)->va_size = fxdr_hyper(tl);
 1382         }
 1383         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1384         if (tl == NULL)
 1385                 return EBADRPC;
 1386         switch (fxdr_unsigned(int, *tl)) {
 1387         case NFSV3SATTRTIME_TOCLIENT:
 1388                 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
 1389                 if (tl == NULL)
 1390                         return EBADRPC;
 1391                 fxdr_nfsv3time(tl, &(a)->va_atime);
 1392                 break;
 1393         case NFSV3SATTRTIME_TOSERVER:
 1394                 getnanotime(&(a)->va_atime);
 1395                 break;
 1396         }
 1397         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
 1398         if (tl == NULL)
 1399                 return EBADRPC;
 1400         switch (fxdr_unsigned(int, *tl)) {
 1401         case NFSV3SATTRTIME_TOCLIENT:
 1402                 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
 1403                 if (tl == NULL)
 1404                         return EBADRPC;
 1405                 fxdr_nfsv3time(tl, &(a)->va_mtime);
 1406                 break;
 1407         case NFSV3SATTRTIME_TOSERVER:
 1408                 getnanotime(&(a)->va_mtime);
 1409                 break;
 1410         }
 1411         return 0;
 1412 }

Cache object: 16b55f9c999355006c117f8db7ae986f


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