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

Cache object: 7bced4a9524d3edfaaf60449596ec1be


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