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

Cache object: 029d0dc9680503c508816482a97efeff


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