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

Cache object: 5e8a6cccf1599e073b23abdd09ab32c8


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