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

Cache object: d0b051370e83380c2cdeaea24f035cab


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