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.2/sys/nfsserver/nfs_srvsubs.c 165860 2007-01-07 13:22:49Z hrs $");
   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_drain(&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                 nfsrv_destroycache();   /* Free the server request cache */
  572                 mtx_destroy(&nfsd_mtx);
  573                 break;
  574         default:
  575                 error = EOPNOTSUPP;
  576                 break;
  577         }
  578         NET_UNLOCK_GIANT();
  579         return error;
  580 }
  581 static moduledata_t nfsserver_mod = {
  582         "nfsserver",
  583         nfsrv_modevent,
  584         NULL,
  585 };
  586 DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
  587 
  588 /* So that loader and kldload(2) can find us, wherever we are.. */
  589 MODULE_VERSION(nfsserver, 1);
  590 
  591 /*
  592  * Set up nameidata for a lookup() call and do it.
  593  *
  594  * If pubflag is set, this call is done for a lookup operation on the
  595  * public filehandle. In that case we allow crossing mountpoints and
  596  * absolute pathnames. However, the caller is expected to check that
  597  * the lookup result is within the public fs, and deny access if
  598  * it is not.
  599  *
  600  * nfs_namei() clears out garbage fields that namei() might leave garbage.
  601  * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
  602  * error occurs but the parent was not requested.
  603  *
  604  * dirp may be set whether an error is returned or not, and must be
  605  * released by the caller.
  606  */
  607 int
  608 nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
  609     struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp,
  610     caddr_t *dposp, struct vnode **retdirp, int v3, struct vattr *retdirattrp,
  611     int *retdirattr_retp, struct thread *td, int pubflag)
  612 {
  613         int i, rem;
  614         struct mbuf *md;
  615         char *fromcp, *tocp, *cp;
  616         struct iovec aiov;
  617         struct uio auio;
  618         struct vnode *dp;
  619         int error, rdonly, linklen;
  620         struct componentname *cnp = &ndp->ni_cnd;
  621         int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0;
  622 
  623         NFSD_LOCK_ASSERT();
  624         NFSD_UNLOCK();
  625         mtx_lock(&Giant);       /* VFS */
  626 
  627         *retdirp = NULL;
  628         cnp->cn_flags |= NOMACCHECK;
  629         cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
  630 
  631         /*
  632          * Copy the name from the mbuf list to ndp->ni_pnbuf
  633          * and set the various ndp fields appropriately.
  634          */
  635         fromcp = *dposp;
  636         tocp = cnp->cn_pnbuf;
  637         md = *mdp;
  638         rem = mtod(md, caddr_t) + md->m_len - fromcp;
  639         for (i = 0; i < len; i++) {
  640                 while (rem == 0) {
  641                         md = md->m_next;
  642                         if (md == NULL) {
  643                                 error = EBADRPC;
  644                                 goto out;
  645                         }
  646                         fromcp = mtod(md, caddr_t);
  647                         rem = md->m_len;
  648                 }
  649                 if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
  650                         error = EACCES;
  651                         goto out;
  652                 }
  653                 *tocp++ = *fromcp++;
  654                 rem--;
  655         }
  656         *tocp = '\0';
  657         *mdp = md;
  658         *dposp = fromcp;
  659         len = nfsm_rndup(len)-len;
  660         if (len > 0) {
  661                 if (rem >= len)
  662                         *dposp += len;
  663                 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
  664                         goto out;
  665         }
  666 
  667         /*
  668          * Extract and set starting directory.
  669          */
  670         mtx_unlock(&Giant);     /* VFS */
  671         NFSD_LOCK();
  672         error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
  673             nam, &rdonly, pubflag);
  674         NFSD_UNLOCK();
  675         mtx_lock(&Giant);       /* VFS */
  676         if (error)
  677                 goto out;
  678         if (dp->v_type != VDIR) {
  679                 vrele(dp);
  680                 error = ENOTDIR;
  681                 goto out;
  682         }
  683 
  684         if (rdonly)
  685                 cnp->cn_flags |= RDONLY;
  686 
  687         /*
  688          * Set return directory.  Reference to dp is implicitly transfered
  689          * to the returned pointer
  690          */
  691         *retdirp = dp;
  692         if (v3) {
  693                 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
  694                 *retdirattr_retp = VOP_GETATTR(dp, retdirattrp,
  695                         ndp->ni_cnd.cn_cred, td);
  696                 VOP_UNLOCK(dp, 0, td);
  697         }
  698 
  699         if (pubflag) {
  700                 /*
  701                  * Oh joy. For WebNFS, handle those pesky '%' escapes,
  702                  * and the 'native path' indicator.
  703                  */
  704                 cp = uma_zalloc(namei_zone, M_WAITOK);
  705                 fromcp = cnp->cn_pnbuf;
  706                 tocp = cp;
  707                 if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
  708                         switch ((unsigned char)*fromcp) {
  709                         case WEBNFS_NATIVE_CHAR:
  710                                 /*
  711                                  * 'Native' path for us is the same
  712                                  * as a path according to the NFS spec,
  713                                  * just skip the escape char.
  714                                  */
  715                                 fromcp++;
  716                                 break;
  717                         /*
  718                          * More may be added in the future, range 0x80-0xff
  719                          */
  720                         default:
  721                                 error = EIO;
  722                                 uma_zfree(namei_zone, cp);
  723                                 goto out;
  724                         }
  725                 }
  726                 /*
  727                  * Translate the '%' escapes, URL-style.
  728                  */
  729                 while (*fromcp != '\0') {
  730                         if (*fromcp == WEBNFS_ESC_CHAR) {
  731                                 if (fromcp[1] != '\0' && fromcp[2] != '\0') {
  732                                         fromcp++;
  733                                         *tocp++ = HEXSTRTOI(fromcp);
  734                                         fromcp += 2;
  735                                         continue;
  736                                 } else {
  737                                         error = ENOENT;
  738                                         uma_zfree(namei_zone, cp);
  739                                         goto out;
  740                                 }
  741                         } else
  742                                 *tocp++ = *fromcp++;
  743                 }
  744                 *tocp = '\0';
  745                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  746                 cnp->cn_pnbuf = cp;
  747         }
  748 
  749         ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
  750         ndp->ni_segflg = UIO_SYSSPACE;
  751 
  752         if (pubflag) {
  753                 ndp->ni_rootdir = rootvnode;
  754                 ndp->ni_loopcnt = 0;
  755                 if (cnp->cn_pnbuf[0] == '/')
  756                         dp = rootvnode;
  757         } else {
  758                 cnp->cn_flags |= NOCROSSMOUNT;
  759         }
  760 
  761         /*
  762          * Initialize for scan, set ni_startdir and bump ref on dp again
  763          * because lookup() will dereference ni_startdir.
  764          */
  765 
  766         cnp->cn_thread = td;
  767         VREF(dp);
  768         ndp->ni_startdir = dp;
  769 
  770         if (!lockleaf)
  771                 cnp->cn_flags |= LOCKLEAF;
  772         for (;;) {
  773                 cnp->cn_nameptr = cnp->cn_pnbuf;
  774                 /*
  775                  * Call lookup() to do the real work.  If an error occurs,
  776                  * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
  777                  * we do not have to dereference anything before returning.
  778                  * In either case ni_startdir will be dereferenced and NULLed
  779                  * out.
  780                  */
  781                 error = lookup(ndp);
  782                 if (error)
  783                         break;
  784 
  785                 /*
  786                  * Check for encountering a symbolic link.  Trivial
  787                  * termination occurs if no symlink encountered.
  788                  * Note: zfree is safe because error is 0, so we will
  789                  * not zfree it again when we break.
  790                  */
  791                 if ((cnp->cn_flags & ISSYMLINK) == 0) {
  792                         if (cnp->cn_flags & (SAVENAME | SAVESTART))
  793                                 cnp->cn_flags |= HASBUF;
  794                         else
  795                                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  796                         if (ndp->ni_vp && !lockleaf)
  797                                 VOP_UNLOCK(ndp->ni_vp, 0, td);
  798                         break;
  799                 }
  800 
  801                 /*
  802                  * Validate symlink
  803                  */
  804                 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
  805                         VOP_UNLOCK(ndp->ni_dvp, 0, td);
  806                 if (!pubflag) {
  807                         error = EINVAL;
  808                         goto badlink2;
  809                 }
  810 
  811                 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
  812                         error = ELOOP;
  813                         goto badlink2;
  814                 }
  815                 if (ndp->ni_pathlen > 1)
  816                         cp = uma_zalloc(namei_zone, M_WAITOK);
  817                 else
  818                         cp = cnp->cn_pnbuf;
  819                 aiov.iov_base = cp;
  820                 aiov.iov_len = MAXPATHLEN;
  821                 auio.uio_iov = &aiov;
  822                 auio.uio_iovcnt = 1;
  823                 auio.uio_offset = 0;
  824                 auio.uio_rw = UIO_READ;
  825                 auio.uio_segflg = UIO_SYSSPACE;
  826                 auio.uio_td = NULL;
  827                 auio.uio_resid = MAXPATHLEN;
  828                 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
  829                 if (error) {
  830                 badlink1:
  831                         if (ndp->ni_pathlen > 1)
  832                                 uma_zfree(namei_zone, cp);
  833                 badlink2:
  834                         vput(ndp->ni_vp);
  835                         vrele(ndp->ni_dvp);
  836                         break;
  837                 }
  838                 linklen = MAXPATHLEN - auio.uio_resid;
  839                 if (linklen == 0) {
  840                         error = ENOENT;
  841                         goto badlink1;
  842                 }
  843                 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
  844                         error = ENAMETOOLONG;
  845                         goto badlink1;
  846                 }
  847 
  848                 /*
  849                  * Adjust or replace path
  850                  */
  851                 if (ndp->ni_pathlen > 1) {
  852                         bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
  853                         uma_zfree(namei_zone, cnp->cn_pnbuf);
  854                         cnp->cn_pnbuf = cp;
  855                 } else
  856                         cnp->cn_pnbuf[linklen] = '\0';
  857                 ndp->ni_pathlen += linklen;
  858 
  859                 /*
  860                  * Cleanup refs for next loop and check if root directory
  861                  * should replace current directory.  Normally ni_dvp
  862                  * becomes the new base directory and is cleaned up when
  863                  * we loop.  Explicitly null pointers after invalidation
  864                  * to clarify operation.
  865                  */
  866                 vput(ndp->ni_vp);
  867                 ndp->ni_vp = NULL;
  868 
  869                 if (cnp->cn_pnbuf[0] == '/') {
  870                         vrele(ndp->ni_dvp);
  871                         ndp->ni_dvp = ndp->ni_rootdir;
  872                         VREF(ndp->ni_dvp);
  873                 }
  874                 ndp->ni_startdir = ndp->ni_dvp;
  875                 ndp->ni_dvp = NULL;
  876         }
  877         if (!lockleaf)
  878                 cnp->cn_flags &= ~LOCKLEAF;
  879         if (cnp->cn_flags & GIANTHELD) {
  880                 mtx_unlock(&Giant);
  881                 cnp->cn_flags &= ~GIANTHELD;
  882         }
  883 
  884         /*
  885          * nfs_namei() guarentees that fields will not contain garbage
  886          * whether an error occurs or not.  This allows the caller to track
  887          * cleanup state trivially.
  888          */
  889 out:
  890         if (error) {
  891                 uma_zfree(namei_zone, cnp->cn_pnbuf);
  892                 ndp->ni_vp = NULL;
  893                 ndp->ni_dvp = NULL;
  894                 ndp->ni_startdir = NULL;
  895                 cnp->cn_flags &= ~HASBUF;
  896         } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
  897                 ndp->ni_dvp = NULL;
  898         }
  899         mtx_unlock(&Giant);     /* VFS */
  900         NFSD_LOCK();
  901         return (error);
  902 }
  903 
  904 /*
  905  * A fiddled version of m_adj() that ensures null fill to a long
  906  * boundary and only trims off the back end
  907  */
  908 void
  909 nfsm_adj(struct mbuf *mp, int len, int nul)
  910 {
  911         struct mbuf *m;
  912         int count, i;
  913         char *cp;
  914 
  915         NFSD_LOCK_DONTCARE();
  916 
  917         /*
  918          * Trim from tail.  Scan the mbuf chain,
  919          * calculating its length and finding the last mbuf.
  920          * If the adjustment only affects this mbuf, then just
  921          * adjust and return.  Otherwise, rescan and truncate
  922          * after the remaining size.
  923          */
  924         count = 0;
  925         m = mp;
  926         for (;;) {
  927                 count += m->m_len;
  928                 if (m->m_next == NULL)
  929                         break;
  930                 m = m->m_next;
  931         }
  932         if (m->m_len > len) {
  933                 m->m_len -= len;
  934                 if (nul > 0) {
  935                         cp = mtod(m, caddr_t)+m->m_len-nul;
  936                         for (i = 0; i < nul; i++)
  937                                 *cp++ = '\0';
  938                 }
  939                 return;
  940         }
  941         count -= len;
  942         if (count < 0)
  943                 count = 0;
  944         /*
  945          * Correct length for chain is "count".
  946          * Find the mbuf with last data, adjust its length,
  947          * and toss data from remaining mbufs on chain.
  948          */
  949         for (m = mp; m; m = m->m_next) {
  950                 if (m->m_len >= count) {
  951                         m->m_len = count;
  952                         if (nul > 0) {
  953                                 cp = mtod(m, caddr_t)+m->m_len-nul;
  954                                 for (i = 0; i < nul; i++)
  955                                         *cp++ = '\0';
  956                         }
  957                         if (m->m_next != NULL) {
  958                                 m_freem(m->m_next);
  959                                 m->m_next = NULL;
  960                         }
  961                         break;
  962                 }
  963                 count -= m->m_len;
  964         }
  965 }
  966 
  967 /*
  968  * Make these functions instead of macros, so that the kernel text size
  969  * doesn't get too big...
  970  */
  971 void
  972 nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
  973     struct vattr *before_vap, int after_ret, struct vattr *after_vap,
  974     struct mbuf **mbp, char **bposp)
  975 {
  976         struct mbuf *mb = *mbp;
  977         char *bpos = *bposp;
  978         u_int32_t *tl;
  979 
  980         if (before_ret) {
  981                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  982                 *tl = nfsrv_nfs_false;
  983         } else {
  984                 tl = nfsm_build(u_int32_t *, 7 * NFSX_UNSIGNED);
  985                 *tl++ = nfsrv_nfs_true;
  986                 txdr_hyper(before_vap->va_size, tl);
  987                 tl += 2;
  988                 txdr_nfsv3time(&(before_vap->va_mtime), tl);
  989                 tl += 2;
  990                 txdr_nfsv3time(&(before_vap->va_ctime), tl);
  991         }
  992         *bposp = bpos;
  993         *mbp = mb;
  994         nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
  995 }
  996 
  997 void
  998 nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
  999     struct vattr *after_vap, struct mbuf **mbp, char **bposp)
 1000 {
 1001         struct mbuf *mb = *mbp;
 1002         char *bpos = *bposp;
 1003         u_int32_t *tl;
 1004         struct nfs_fattr *fp;
 1005 
 1006         if (after_ret) {
 1007                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
 1008                 *tl = nfsrv_nfs_false;
 1009         } else {
 1010                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
 1011                 *tl++ = nfsrv_nfs_true;
 1012                 fp = (struct nfs_fattr *)tl;
 1013                 nfsm_srvfattr(nfsd, after_vap, fp);
 1014         }
 1015         *mbp = mb;
 1016         *bposp = bpos;
 1017 }
 1018 
 1019 void
 1020 nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
 1021     struct nfs_fattr *fp)
 1022 {
 1023 
 1024         fp->fa_nlink = txdr_unsigned(vap->va_nlink);
 1025         fp->fa_uid = txdr_unsigned(vap->va_uid);
 1026         fp->fa_gid = txdr_unsigned(vap->va_gid);
 1027         if (nfsd->nd_flag & ND_NFSV3) {
 1028                 fp->fa_type = vtonfsv3_type(vap->va_type);
 1029                 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
 1030                 txdr_hyper(vap->va_size, &fp->fa3_size);
 1031                 txdr_hyper(vap->va_bytes, &fp->fa3_used);
 1032                 fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
 1033                 fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
 1034                 fp->fa3_fsid.nfsuquad[0] = 0;
 1035                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
 1036                 fp->fa3_fileid.nfsuquad[0] = 0;
 1037                 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
 1038                 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
 1039                 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
 1040                 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
 1041         } else {
 1042                 fp->fa_type = vtonfsv2_type(vap->va_type);
 1043                 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1044                 fp->fa2_size = txdr_unsigned(vap->va_size);
 1045                 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
 1046                 if (vap->va_type == VFIFO)
 1047                         fp->fa2_rdev = 0xffffffff;
 1048                 else
 1049                         fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
 1050                 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
 1051                 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
 1052                 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
 1053                 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
 1054                 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
 1055                 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
 1056         }
 1057 }
 1058 
 1059 /*
 1060  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
 1061  *      - look up fsid in mount list (if not found ret error)
 1062  *      - get vp and export rights by calling VFS_FHTOVP()
 1063  *      - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
 1064  *      - if not lockflag unlock it with VOP_UNLOCK()
 1065  */
 1066 int
 1067 nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
 1068     struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
 1069     int *rdonlyp, int pubflag)
 1070 {
 1071         struct thread *td = curthread; /* XXX */
 1072         struct mount *mp;
 1073         int i;
 1074         struct ucred *credanon;
 1075         int error, exflags;
 1076         int vfslocked;
 1077 #ifdef MNT_EXNORESPORT          /* XXX needs mountd and /etc/exports help yet */
 1078         struct sockaddr_int *saddr;
 1079 #endif
 1080 
 1081         NFSD_LOCK_ASSERT();
 1082 
 1083         *vpp = NULL;
 1084 
 1085         if (nfs_ispublicfh(fhp)) {
 1086                 if (!pubflag || !nfs_pub.np_valid)
 1087                         return (ESTALE);
 1088                 fhp = &nfs_pub.np_handle;
 1089         }
 1090 
 1091         mp = vfs_getvfs(&fhp->fh_fsid);
 1092         if (!mp)
 1093                 return (ESTALE);
 1094         NFSD_UNLOCK();
 1095         vfslocked = VFS_LOCK_GIANT(mp);
 1096         error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
 1097         if (error)
 1098                 goto out;
 1099         error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
 1100         if (error)
 1101                 goto out;
 1102 #ifdef MNT_EXNORESPORT
 1103         if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
 1104                 saddr = (struct sockaddr_in *)nam;
 1105                 if ((saddr->sin_family == AF_INET ||
 1106                      saddr->sin_family == AF_INET6) &&
 1107         /* same code for INET and INET6: sin*_port at same offet */
 1108                     ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
 1109                         vput(*vpp);
 1110                         *vpp = NULL;
 1111                         error = NFSERR_AUTHERR | AUTH_TOOWEAK;
 1112                 }
 1113         }
 1114 #endif
 1115         /*
 1116          * Check/setup credentials.
 1117          */
 1118         if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
 1119                 cred->cr_uid = credanon->cr_uid;
 1120                 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
 1121                         cred->cr_groups[i] = credanon->cr_groups[i];
 1122                 cred->cr_ngroups = i;
 1123         }
 1124         if (exflags & MNT_EXRDONLY)
 1125                 *rdonlyp = 1;
 1126         else
 1127                 *rdonlyp = 0;
 1128 
 1129         if (!lockflag)
 1130                 VOP_UNLOCK(*vpp, 0, td);
 1131 out:
 1132         vfs_rel(mp);
 1133         VFS_UNLOCK_GIANT(vfslocked);
 1134         NFSD_LOCK();
 1135         return (error);
 1136 }
 1137 
 1138 
 1139 /*
 1140  * WebNFS: check if a filehandle is a public filehandle. For v3, this
 1141  * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
 1142  * transformed this to all zeroes in both cases, so check for it.
 1143  */
 1144 int
 1145 nfs_ispublicfh(fhandle_t *fhp)
 1146 {
 1147         char *cp = (char *)fhp;
 1148         int i;
 1149 
 1150         NFSD_LOCK_DONTCARE();
 1151 
 1152         for (i = 0; i < NFSX_V3FH; i++)
 1153                 if (*cp++ != 0)
 1154                         return (FALSE);
 1155         return (TRUE);
 1156 }
 1157 
 1158 /*
 1159  * This function compares two net addresses by family and returns TRUE
 1160  * if they are the same host.
 1161  * If there is any doubt, return FALSE.
 1162  * The AF_INET family is handled as a special case so that address mbufs
 1163  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
 1164  */
 1165 int
 1166 netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
 1167 {
 1168         struct sockaddr_in *inetaddr;
 1169 
 1170         NFSD_LOCK_DONTCARE();
 1171 
 1172         switch (family) {
 1173         case AF_INET:
 1174                 inetaddr = (struct sockaddr_in *)nam;
 1175                 if (inetaddr->sin_family == AF_INET &&
 1176                     inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
 1177                         return (1);
 1178                 break;
 1179 #ifdef INET6
 1180         case AF_INET6:
 1181         {
 1182                 register struct sockaddr_in6 *inet6addr1, *inet6addr2;
 1183 
 1184                 inet6addr1 = (struct sockaddr_in6 *)nam;
 1185                 inet6addr2 = (struct sockaddr_in6 *)haddr->had_nam;
 1186         /* XXX - should test sin6_scope_id ? */
 1187                 if (inet6addr1->sin6_family == AF_INET6 &&
 1188                     IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
 1189                                        &inet6addr2->sin6_addr))
 1190                         return (1);
 1191                 break;
 1192         }
 1193 #endif
 1194         default:
 1195                 break;
 1196         };
 1197         return (0);
 1198 }
 1199 
 1200 /*
 1201  * Map errnos to NFS error numbers. For Version 3 also filter out error
 1202  * numbers not specified for the associated procedure.
 1203  */
 1204 int
 1205 nfsrv_errmap(struct nfsrv_descript *nd, int err)
 1206 {
 1207         const short *defaulterrp, *errp;
 1208         int e;
 1209 
 1210         NFSD_LOCK_DONTCARE();
 1211 
 1212         if (nd->nd_flag & ND_NFSV3) {
 1213             if (nd->nd_procnum <= NFSPROC_COMMIT) {
 1214                 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
 1215                 while (*++errp) {
 1216                         if (*errp == err)
 1217                                 return (err);
 1218                         else if (*errp > err)
 1219                                 break;
 1220                 }
 1221                 return ((int)*defaulterrp);
 1222             } else
 1223                 return (err & 0xffff);
 1224         }
 1225         e = 0;
 1226         if (err <= ELAST)
 1227                 e = nfsrv_v2errmap[err - 1];
 1228         if (e != 0)
 1229                 return (e);
 1230         return (NFSERR_IO);
 1231 }
 1232 
 1233 /*
 1234  * Sort the group list in increasing numerical order.
 1235  * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
 1236  *  that used to be here.)
 1237  */
 1238 void
 1239 nfsrvw_sort(gid_t *list, int num)
 1240 {
 1241         int i, j;
 1242         gid_t v;
 1243 
 1244         NFSD_LOCK_DONTCARE();
 1245 
 1246         /* Insertion sort. */
 1247         for (i = 1; i < num; i++) {
 1248                 v = list[i];
 1249                 /* find correct slot for value v, moving others up */
 1250                 for (j = i; --j >= 0 && v < list[j];)
 1251                         list[j + 1] = list[j];
 1252                 list[j + 1] = v;
 1253         }
 1254 }
 1255 
 1256 /*
 1257  * copy credentials making sure that the result can be compared with bcmp().
 1258  */
 1259 void
 1260 nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
 1261 {
 1262         int i;
 1263 
 1264         NFSD_LOCK_DONTCARE();
 1265 
 1266         bzero((caddr_t)outcred, sizeof (struct ucred));
 1267         outcred->cr_ref = 1;
 1268         outcred->cr_uid = incred->cr_uid;
 1269         outcred->cr_ngroups = incred->cr_ngroups;
 1270         for (i = 0; i < incred->cr_ngroups; i++)
 1271                 outcred->cr_groups[i] = incred->cr_groups[i];
 1272         nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
 1273 }
 1274 
 1275 /*
 1276  * Helper functions for macros.
 1277  */
 1278 
 1279 void
 1280 nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos)
 1281 {
 1282         u_int32_t *tl;
 1283 
 1284         NFSD_LOCK_DONTCARE();
 1285 
 1286         if (v3) {
 1287                 tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
 1288                 *tl++ = txdr_unsigned(NFSX_V3FH);
 1289                 bcopy(f, tl, NFSX_V3FH);
 1290         } else {
 1291                 tl = nfsm_build_xx(NFSX_V2FH, mb, bpos);
 1292                 bcopy(f, tl, NFSX_V2FH);
 1293         }
 1294 }
 1295 
 1296 void
 1297 nfsm_srvpostop_fh_xx(fhandle_t *f, struct mbuf **mb, caddr_t *bpos)
 1298 {
 1299         u_int32_t *tl;
 1300 
 1301         tl = nfsm_build_xx(2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
 1302         *tl++ = nfsrv_nfs_true;
 1303         *tl++ = txdr_unsigned(NFSX_V3FH);
 1304         bcopy(f, tl, NFSX_V3FH);
 1305 }
 1306 
 1307 int
 1308 nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
 1309 {
 1310         u_int32_t *tl;
 1311 
 1312         NFSD_LOCK_DONTCARE();
 1313 
 1314         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1315         if (tl == NULL)
 1316                 return EBADRPC;
 1317         *s = fxdr_unsigned(int32_t, *tl);
 1318         if (*s > m || *s <= 0)
 1319                 return EBADRPC;
 1320         return 0;
 1321 }
 1322 
 1323 int
 1324 nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
 1325 {
 1326         u_int32_t *tl;
 1327 
 1328         NFSD_LOCK_DONTCARE();
 1329 
 1330         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1331         if (tl == NULL)
 1332                 return EBADRPC;
 1333         *s = fxdr_unsigned(int32_t, *tl);
 1334         if (*s > m)
 1335                 return NFSERR_NAMETOL;
 1336         if (*s <= 0)
 1337                 return EBADRPC;
 1338         return 0;
 1339 }
 1340 
 1341 int
 1342 nfsm_srvnamesiz0_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
 1343 {
 1344         u_int32_t *tl;
 1345 
 1346         NFSD_LOCK_DONTCARE();
 1347 
 1348         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1349         if (tl == NULL)
 1350                 return EBADRPC;
 1351         *s = fxdr_unsigned(int32_t, *tl);
 1352         if (*s > m)
 1353                 return NFSERR_NAMETOL;
 1354         if (*s < 0)
 1355                 return EBADRPC;
 1356         return 0;
 1357 }
 1358 
 1359 void
 1360 nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
 1361     char **bp, char **be, caddr_t bpos, int droplock)
 1362 {
 1363         struct mbuf *nmp;
 1364 
 1365         NFSD_LOCK_DONTCARE();
 1366 
 1367         if (droplock)
 1368                 NFSD_LOCK_ASSERT();
 1369         else
 1370                 NFSD_UNLOCK_ASSERT();
 1371 
 1372         if (*bp >= *be) {
 1373                 if (*mp == mb)
 1374                         (*mp)->m_len += *bp - bpos;
 1375                 if (droplock)
 1376                         NFSD_UNLOCK();
 1377                 MGET(nmp, M_TRYWAIT, MT_DATA);
 1378                 MCLGET(nmp, M_TRYWAIT);
 1379                 if (droplock)
 1380                         NFSD_LOCK();
 1381                 nmp->m_len = NFSMSIZ(nmp);
 1382                 (*mp)->m_next = nmp;
 1383                 *mp = nmp;
 1384                 *bp = mtod(*mp, caddr_t);
 1385                 *be = *bp + (*mp)->m_len;
 1386         }
 1387         *tl = (u_int32_t *)*bp;
 1388 }
 1389 
 1390 int
 1391 nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md,
 1392     caddr_t *dpos)
 1393 {
 1394         u_int32_t *tl;
 1395         int fhlen;
 1396 
 1397         NFSD_LOCK_DONTCARE();
 1398 
 1399         if (nfsd->nd_flag & ND_NFSV3) {
 1400                 tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1401                 if (tl == NULL)
 1402                         return EBADRPC;
 1403                 fhlen = fxdr_unsigned(int, *tl);
 1404                 if (fhlen != 0 && fhlen != NFSX_V3FH)
 1405                         return EBADRPC;
 1406         } else {
 1407                 fhlen = NFSX_V2FH;
 1408         }
 1409         if (fhlen != 0) {
 1410                 tl = nfsm_dissect_xx_nonblock(fhlen, md, dpos);
 1411                 if (tl == NULL)
 1412                         return EBADRPC;
 1413                 bcopy((caddr_t)tl, (caddr_t)(f), fhlen);
 1414         } else {
 1415                 bzero((caddr_t)(f), NFSX_V3FH);
 1416         }
 1417         return 0;
 1418 }
 1419 
 1420 int
 1421 nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
 1422 {
 1423         u_int32_t *tl;
 1424         int toclient = 0;
 1425 
 1426         NFSD_LOCK_DONTCARE();
 1427 
 1428         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1429         if (tl == NULL)
 1430                 return EBADRPC;
 1431         if (*tl == nfsrv_nfs_true) {
 1432                 tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1433                 if (tl == NULL)
 1434                         return EBADRPC;
 1435                 (a)->va_mode = nfstov_mode(*tl);
 1436         }
 1437         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1438         if (tl == NULL)
 1439                 return EBADRPC;
 1440         if (*tl == nfsrv_nfs_true) {
 1441                 tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1442                 if (tl == NULL)
 1443                         return EBADRPC;
 1444                 (a)->va_uid = fxdr_unsigned(uid_t, *tl);
 1445         }
 1446         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1447         if (tl == NULL)
 1448                 return EBADRPC;
 1449         if (*tl == nfsrv_nfs_true) {
 1450                 tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1451                 if (tl == NULL)
 1452                         return EBADRPC;
 1453                 (a)->va_gid = fxdr_unsigned(gid_t, *tl);
 1454         }
 1455         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1456         if (tl == NULL)
 1457                 return EBADRPC;
 1458         if (*tl == nfsrv_nfs_true) {
 1459                 tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
 1460                 if (tl == NULL)
 1461                         return EBADRPC;
 1462                 (a)->va_size = fxdr_hyper(tl);
 1463         }
 1464         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1465         if (tl == NULL)
 1466                 return EBADRPC;
 1467         switch (fxdr_unsigned(int, *tl)) {
 1468         case NFSV3SATTRTIME_TOCLIENT:
 1469                 tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
 1470                 if (tl == NULL)
 1471                         return EBADRPC;
 1472                 fxdr_nfsv3time(tl, &(a)->va_atime);
 1473                 toclient = 1;
 1474                 break;
 1475         case NFSV3SATTRTIME_TOSERVER:
 1476                 getnanotime(&(a)->va_atime);
 1477                 a->va_vaflags |= VA_UTIMES_NULL;
 1478                 break;
 1479         }
 1480         tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
 1481         if (tl == NULL)
 1482                 return EBADRPC;
 1483         switch (fxdr_unsigned(int, *tl)) {
 1484         case NFSV3SATTRTIME_TOCLIENT:
 1485                 tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
 1486                 if (tl == NULL)
 1487                         return EBADRPC;
 1488                 fxdr_nfsv3time(tl, &(a)->va_mtime);
 1489                 a->va_vaflags &= ~VA_UTIMES_NULL;
 1490                 break;
 1491         case NFSV3SATTRTIME_TOSERVER:
 1492                 getnanotime(&(a)->va_mtime);
 1493                 if (toclient == 0)
 1494                         a->va_vaflags |= VA_UTIMES_NULL;
 1495                 break;
 1496         }
 1497         return 0;
 1498 }

Cache object: 789cfef5407876a0c5f374be1893ef6f


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