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/nfs4client/nfs4_subs.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 /* $FreeBSD$ */
    2 /* $Id: nfs4_subs.c,v 1.52 2003/11/05 14:58:59 rees Exp $ */
    3 
    4 /*-
    5  * copyright (c) 2003
    6  * the regents of the university of michigan
    7  * all rights reserved
    8  * 
    9  * permission is granted to use, copy, create derivative works and redistribute
   10  * this software and such derivative works for any purpose, so long as the name
   11  * of the university of michigan is not used in any advertising or publicity
   12  * pertaining to the use or distribution of this software without specific,
   13  * written prior authorization.  if the above copyright notice or any other
   14  * identification of the university of michigan is included in any copy of any
   15  * portion of this software, then the disclaimer below must also be included.
   16  * 
   17  * this software is provided as is, without representation from the university
   18  * of michigan as to its fitness for any purpose, and without warranty by the
   19  * university of michigan of any kind, either express or implied, including
   20  * without limitation the implied warranties of merchantability and fitness for
   21  * a particular purpose. the regents of the university of michigan shall not be
   22  * liable for any damages, including special, indirect, incidental, or
   23  * consequential damages, with respect to any claim arising out of or in
   24  * connection with the use of the software, even if it has been or is hereafter
   25  * advised of the possibility of such damages.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bio.h>
   34 #include <sys/buf.h>
   35 #include <sys/proc.h>
   36 #include <sys/mount.h>
   37 #include <sys/vnode.h>
   38 #include <sys/namei.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/socket.h>
   41 #include <sys/stat.h>
   42 #include <sys/malloc.h>
   43 #include <sys/sysent.h>
   44 #include <sys/syscall.h>
   45 #include <sys/sysproto.h>
   46 #include <sys/fcntl.h>
   47 
   48 #include <machine/stdarg.h>
   49 
   50 #include <vm/vm.h>
   51 #include <vm/vm_object.h>
   52 #include <vm/vm_extern.h>
   53 #include <vm/uma.h>
   54 
   55 #include <rpc/rpcclnt.h>
   56 
   57 #include <nfs/rpcv2.h>
   58 #include <nfs/nfsproto.h>
   59 #include <nfsclient/nfs.h>
   60 #include <nfs4client/nfs4.h>
   61 #include <nfsclient/nfsnode.h>
   62 #include <nfsclient/nfsmount.h>
   63 #include <nfs/xdr_subs.h>
   64 #include <nfsclient/nfsm_subs.h>
   65 
   66 #include <nfs4client/nfs4_dev.h>
   67 #include <nfs4client/nfs4_idmap.h>
   68 #include <nfs4client/nfs4m_subs.h>
   69 
   70 #include <netinet/in.h>
   71 
   72 #define NFSM_DISSECT(s) do {                                                    \
   73         tl = nfsm_dissect_xx((s), md, dpos);                                    \
   74         if (tl == NULL) {                                                       \
   75                 printf("NFSM_DISSECT error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__);  \
   76                 return (EBADRPC);                                               \
   77         }                                                                       \
   78 } while (0)
   79 
   80 #define NFSM_ADV(s) do {                                                \
   81         t1 = nfsm_adv_xx((s), md, dpos);                                \
   82         if (t1 != 0) {                                                  \
   83                 printf("NFSM_ADV error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__);      \
   84                 return (EBADRPC);                                       \
   85         }                                                               \
   86 } while (0)
   87 
   88 #define NFSM_MTOTIME(t) do {                            \
   89         NFSM_DISSECT(3 * NFSX_UNSIGNED);                \
   90         (t).tv_sec = fxdr_hyper(tl);                    \
   91         tl += 2;                                        \
   92         (t).tv_nsec = fxdr_unsigned(long, *tl++);       \
   93 } while (0)
   94 
   95 static uint32_t __fsinfo_bm[2], __fsattr_bm[2], __getattr_bm[2], __readdir_bm[2];
   96 
   97 nfsv4bitmap nfsv4_fsinfobm = { 2, __fsinfo_bm };
   98 nfsv4bitmap nfsv4_fsattrbm = { 2, __fsattr_bm };
   99 nfsv4bitmap nfsv4_getattrbm = { 2, __getattr_bm };
  100 nfsv4bitmap nfsv4_readdirbm = { 2, __readdir_bm };
  101 
  102 /* Helper routines */
  103 int nfsm_v4build_attrs_xx(struct vattr *, struct mbuf **, caddr_t *);
  104 int nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *,  struct mbuf **, caddr_t *);
  105 
  106 void
  107 nfsm_v4init(void)
  108 {
  109 
  110         /* Set up bitmasks */
  111         FA4_SET(FA4_FSID, __fsinfo_bm);
  112         FA4_SET(FA4_MAXREAD, __fsinfo_bm);
  113         FA4_SET(FA4_MAXWRITE, __fsinfo_bm);
  114         FA4_SET(FA4_LEASE_TIME, __fsinfo_bm);
  115 
  116         FA4_SET(FA4_FSID, __fsattr_bm);
  117         FA4_SET(FA4_FILES_FREE, __fsattr_bm);
  118         FA4_SET(FA4_FILES_TOTAL, __fsattr_bm);
  119         FA4_SET(FA4_SPACE_AVAIL, __fsattr_bm);
  120         FA4_SET(FA4_SPACE_FREE, __fsattr_bm);
  121         FA4_SET(FA4_SPACE_TOTAL, __fsattr_bm);
  122 
  123         FA4_SET(FA4_TYPE, __getattr_bm);
  124         FA4_SET(FA4_FSID, __getattr_bm);
  125         FA4_SET(FA4_SIZE, __getattr_bm);
  126         FA4_SET(FA4_MODE, __getattr_bm);
  127         FA4_SET(FA4_RAWDEV, __getattr_bm);
  128         FA4_SET(FA4_NUMLINKS, __getattr_bm);
  129         FA4_SET(FA4_OWNER, __getattr_bm);
  130         FA4_SET(FA4_OWNER_GROUP, __getattr_bm);
  131         FA4_SET(FA4_FILEID, __getattr_bm);
  132         FA4_SET(FA4_TIME_ACCESS, __getattr_bm);
  133         FA4_SET(FA4_TIME_CREATE, __getattr_bm);
  134         FA4_SET(FA4_TIME_METADATA, __getattr_bm);
  135         FA4_SET(FA4_TIME_MODIFY, __getattr_bm);
  136 
  137         FA4_SET(FA4_TYPE, __readdir_bm);
  138         FA4_SET(FA4_FSID, __readdir_bm);
  139         FA4_SET(FA4_FILEID, __readdir_bm);
  140         FA4_SET(FA4_RDATTR_ERROR, __readdir_bm);
  141 }
  142 
  143 /*
  144  * Util
  145  */
  146 
  147 uint32_t
  148 nfs_v4fileid4_to_fileid(uint64_t fid)
  149 {
  150         return ((uint32_t)((fid >> 32) | fid));
  151 }
  152 
  153 void
  154 nfs_v4initcompound(struct nfs4_compound *cp)
  155 {
  156         bzero(cp, sizeof(*cp));
  157 }
  158 
  159 /*
  160  * Build/dissect XDR buffer with a format string.
  161  *
  162  *    u - unsigned
  163  *    h - hyper
  164  *    s - stringlength, string
  165  *    k - skip length (bytes)
  166  *    a - arraylength, componentlenght, array
  167  *    o - opaque fix length
  168  *    O - opaque var length in bytes
  169  */
  170 
  171 void
  172 nfsm_buildf_xx(struct mbuf **mb, caddr_t *bpos, char *fmt, ...)
  173 {
  174         uint32_t *tl, t1, len, uval;
  175         uint64_t hval;
  176         va_list args;
  177         char *p, *which;
  178 
  179         va_start(args, fmt);
  180         for (which = fmt; *which != '\0'; which++)
  181                 switch (*which) {
  182                 case 'u':       /* Unsigned */
  183                         tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
  184                         uval = va_arg(args, uint32_t);
  185                         *tl++ = txdr_unsigned(uval);
  186                         break;
  187                 case 'h':       /* Hyper */
  188                         tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  189                         hval = va_arg(args, uint64_t);
  190                         txdr_hyper(hval, tl);
  191                         break;
  192                 case 'o':       /* Fixed-length opaque */
  193                         len = va_arg(args, uint32_t);
  194                         p = va_arg(args, char *);
  195                         tl = nfsm_build_xx(nfsm_rndup(len), mb, bpos);
  196                         bcopy(p, tl, len);
  197                         break;
  198                 case 'O':       /* Variable-length opaque */
  199                 case 's':       /* String */
  200                         len = va_arg(args, uint32_t);
  201                         p = va_arg(args, char *);
  202                         t1 = nfsm_strtom_xx(p, len, len, mb, bpos);
  203                         break;
  204                 case 'k':       /* Skip */
  205                         len = va_arg(args, uint32_t);
  206                         nfsm_build_xx(nfsm_rndup(len), mb, bpos);
  207                         break;
  208                 default:
  209                         panic("Invalid buildf string %s[%c]", fmt, *which);
  210                         break;
  211                 }
  212         va_end(args);
  213 }
  214 
  215 int
  216 nfsm_dissectf_xx(struct mbuf **md, caddr_t *dpos, char *fmt, ...)
  217 {
  218         uint32_t *tl, t1, len, *uval;
  219         uint64_t *hval;
  220         va_list args;
  221         char *p, *which;
  222 
  223         va_start(args, fmt);
  224         for (which = fmt; *which != '\0'; which++)
  225                 switch (*which) {
  226                 case 'u':       /* Unsigned */
  227                         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  228                         if (tl == NULL)
  229                                 return (EBADRPC);
  230                         uval = va_arg(args, uint32_t *);
  231                         *uval = fxdr_unsigned(uint32_t, *tl++);
  232                         break;
  233                 case 'h':       /* Hyper */
  234                         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  235                         if (tl == NULL)
  236                                 return (EBADRPC);
  237                         hval = va_arg(args, uint64_t *);
  238                         *hval = fxdr_hyper(tl);
  239                         break;
  240                 case 'o':       /* Fixed-length opaque */
  241                         len = va_arg(args, uint32_t);
  242                         p = va_arg(args, void *);
  243                         tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos);
  244                         if (tl == NULL)
  245                                 return (EBADRPC);
  246                         bcopy(tl, p, len);
  247                         break;
  248                 case 'O':       /* Variable-length opaque */
  249                 case 's':       /* String */
  250                         len = va_arg(args, uint32_t);
  251                         p = va_arg(args, char *);
  252                         tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos);
  253                         if (tl == NULL)
  254                                 return (EBADRPC);
  255                         bcopy(tl, p, len);
  256                         break;
  257                 case 'k':       /* Skip bytes */
  258                         len = va_arg(args, uint32_t);
  259                         t1 = nfsm_adv_xx(nfsm_rndup(len), md, dpos);
  260                         break;
  261                 default:
  262                         panic("Invalid dissectf string %s[%c]", fmt, *which);
  263                         break;
  264                 }
  265         va_end(args);
  266 
  267         return (0);
  268 }
  269 
  270 /*
  271  * XXX - There are a few problems with the way the postops are places
  272  * in the code.  Ideally, they should be taken care of immediately, as
  273  * to avoid uneceesary waits for mutexes, but then we would be
  274  * introducing even more complexity by having to handle two separate
  275  * cases.  Also, since they are placed at the end of the vnops', there
  276  * may be operations which sleep in between, further extending this
  277  * wait.  It is conceivable that there is a deadlock condition there,
  278  * too.
  279  *
  280  * Also, for vnops that do multiple operations, it's inconvenient
  281  * since on error, individual decoding will got nfsmout.
  282  */
  283 
  284 int
  285 nfs_v4postop(struct nfs4_compound *cp, int status)
  286 {
  287         struct nfs4_fctx *fcp = cp->fcp;
  288 
  289         /*
  290          * XXX does the previous result need to be stores with the
  291          * lockowner?  ack, spec is unclear ..
  292          */
  293 
  294         if (fcp != NULL)
  295                 if (cp->seqidused < cp->rep_nops ||
  296                     (cp->seqidused + 1 == cp->rep_nops &&
  297                         NFS4_SEQIDMUTATINGERROR(status)))
  298                         fcp->lop->lo_seqid++;
  299 
  300         return (status);
  301 }
  302 
  303 int
  304 nfs_v4handlestatus(int status, struct nfs4_compound *cp)
  305 {
  306         return (status);
  307 }
  308 
  309 /*
  310  * Initial setup of compound.
  311  */
  312 
  313 int
  314 nfsm_v4build_compound_xx(struct nfs4_compound *cp, char *tag,
  315     struct mbuf **mb, caddr_t *bpos)
  316 {
  317         uint32_t t1, *tl, siz;
  318 
  319         /* Tag */
  320         siz = strlen(tag);
  321         t1 = nfsm_rndup(siz) + NFSX_UNSIGNED;
  322         if (t1 <= M_TRAILINGSPACE(*mb)) {
  323                 tl = nfsm_build_xx(t1, mb, bpos);
  324                 *tl++ = txdr_unsigned(siz);
  325                 *(tl + ((t1 >> 2) - 2)) = 0;
  326                 bcopy(tag, tl, siz);
  327         } else {
  328                 t1 = nfsm_strtmbuf(mb, bpos, (const char *)tag, siz);
  329                 if (t1 != 0)
  330                         return (t1);
  331         }
  332 
  333         /* Minor version and argarray*/
  334         tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  335         *tl++ = txdr_unsigned(NFS4_MINOR_VERSION);
  336         /* Save for backfill */
  337         cp->req_nopsp = tl;
  338         *tl = txdr_unsigned(0);
  339 
  340         cp->curvp = NULL;
  341         cp->savevp = NULL;
  342 
  343         return (0);
  344 }
  345 
  346 /*
  347  * XXX
  348  * - backfill for stateid, and such
  349  */
  350 int
  351 nfsm_v4build_finalize_xx(struct nfs4_compound *cp, struct mbuf **mb, caddr_t *bpos)
  352 {
  353         *cp->req_nopsp = txdr_unsigned(cp->req_nops);
  354 
  355         return (0);
  356 }
  357 
  358 int
  359 nfsm_v4build_putfh_xx(struct nfs4_compound *cp, struct vnode *vp,
  360     struct mbuf **mb, caddr_t *bpos)
  361 {
  362         uint32_t t1;
  363 
  364         /* Op */
  365         nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_PUTFH);
  366 
  367         /* FH */
  368         t1 = nfsm_fhtom_xx(vp, 1, mb, bpos);
  369         if (t1 != 0)
  370                 return (t1);
  371 
  372         cp->req_nops++;
  373         cp->curvp = vp;
  374 
  375         return (0);
  376 }
  377 
  378 int
  379 nfsm_v4build_putfh_nv_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  380     struct mbuf **mb, caddr_t *bpos)
  381 {
  382         nfsm_buildf_xx(mb, bpos, "uuo",
  383             NFSV4OP_PUTFH,
  384             gfh->fh_len,
  385             gfh->fh_len,
  386             &gfh->fh_val);
  387 
  388         cp->req_nops++;
  389 
  390         return (0);
  391 }
  392 
  393 int
  394 nfsm_v4build_simple_xx(struct nfs4_compound *cp, uint32_t op,
  395     struct mbuf **mb, caddr_t *bpos)
  396 {
  397         nfsm_buildf_xx(mb, bpos, "u", op);
  398 
  399         cp->req_nops++;
  400 
  401         return (0);
  402 }
  403 
  404 int
  405 nfsm_v4build_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga,
  406     struct mbuf **mb, caddr_t *bpos)
  407 {
  408         int i;
  409 
  410         /* Op + bitmap length + bitmap */
  411         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_GETATTR, ga->bm->bmlen);
  412         for (i = 0; i < ga->bm->bmlen; i++)
  413                 nfsm_buildf_xx(mb, bpos, "u", ga->bm->bmval[i]);
  414 
  415         ga->vp = cp->curvp;
  416         cp->req_nops++;          
  417 
  418         return (0);
  419 }
  420 
  421 int
  422 nfsm_v4build_setattr_xx(struct nfs4_compound *cp, struct vattr *vap,
  423     struct nfs4_fctx *fcp, struct mbuf **mb, caddr_t *bpos)
  424 {
  425         int error;
  426         static char zero_stateid[NFSX_V4STATEID];
  427 
  428         nfsm_buildf_xx(mb, bpos, "uo",
  429             NFSV4OP_SETATTR,
  430             NFSX_V4STATEID, fcp ? fcp->stateid : zero_stateid);
  431         error = nfsm_v4build_attrs_xx(vap, mb, bpos);
  432         if (error == 0)
  433                 cp->req_nops++;
  434 
  435         return (error);
  436 }
  437 
  438 int
  439 nfsm_v4build_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  440     struct mbuf **mb, caddr_t *bpos)
  441 {
  442         nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_GETFH);
  443 
  444         gfh->vp = cp->curvp;
  445         cp->req_nops++;
  446 
  447         return (0);
  448 }
  449 
  450 int
  451 nfsm_v4build_lookup_xx(struct nfs4_compound *cp, struct nfs4_oparg_lookup *l,
  452     struct mbuf **mb, caddr_t *bpos)
  453 {
  454         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LOOKUP, l->namelen, l->name);
  455 
  456         cp->curvp = l->vp;
  457         cp->req_nops++;
  458 
  459         return (0);
  460 }
  461 
  462 int
  463 nfsm_v4build_setclientid_xx(struct nfs4_compound *cp,
  464     struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
  465 {
  466         struct timeval tv;
  467 
  468         microtime(&tv);
  469 
  470         nfsm_buildf_xx(mb, bpos, "uuusussu",
  471             NFSV4OP_SETCLIENTID,
  472             tv.tv_sec, tv.tv_usec,
  473             sci->namelen, sci->name,
  474             sci->cb_prog,
  475             sci->cb_netidlen, sci->cb_netid,
  476             sci->cb_univaddrlen, sci->cb_univaddr,
  477             0xCA11BACC);
  478 
  479         cp->req_nops++;
  480 
  481         return (0);
  482 }
  483 
  484 int
  485 nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *cp,
  486     struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
  487 {
  488         nfsm_buildf_xx(mb, bpos, "uho",
  489             NFSV4OP_SETCLIENTID_CONFIRM,
  490             sci->clientid,
  491             sizeof(sci->verf), sci->verf);
  492 
  493         cp->req_nops++;
  494 
  495         return (0);
  496 }
  497 
  498 int
  499 nfsm_v4build_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  500     struct mbuf **mb, caddr_t *bpos)
  501 {
  502         int error = 0;
  503         struct nfs4_lowner *lop = op->fcp->lop;
  504 
  505         nfsm_buildf_xx(mb, bpos, "uuuuhuu",
  506             NFSV4OP_OPEN,
  507             lop->lo_seqid,
  508             op->flags & O_ACCMODE,
  509             NFSV4OPENSHARE_DENY_NONE,
  510             cp->nmp->nm_clientid,
  511             4, lop->lo_id);
  512 
  513         if (op->flags & O_CREAT) {
  514                 nfsm_buildf_xx(mb, bpos, "u", OTCREATE);
  515                 /* openflag4: mode */
  516                 nfsm_buildf_xx(mb, bpos, "u", CMUNCHECKED);
  517                 /* openflag4: createattrs... */
  518                 if (op->vap != NULL) {
  519                         if (op->flags & O_TRUNC)
  520                                 op->vap->va_size = 0;
  521                         error = nfsm_v4build_attrs_xx(op->vap, mb, bpos);
  522                         if (error != 0)
  523                                 return (error);
  524                 } else
  525                         nfsm_buildf_xx(mb, bpos, "uu", 0, 0);
  526         } else
  527                 nfsm_buildf_xx(mb, bpos, "u", OTNOCREATE);
  528 
  529         nfsm_buildf_xx(mb, bpos, "us", op->ctype,
  530             op->cnp->cn_namelen, op->cnp->cn_nameptr);
  531 
  532         cp->seqidused = cp->req_nops++;
  533         cp->fcp = op->fcp;
  534 
  535         return (error);
  536 }
  537 
  538 /*
  539  * XXX
  540  * - Wait on recovery
  541  */
  542 int
  543 nfsm_v4build_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  544     struct mbuf **mb, caddr_t *bpos)
  545 {
  546         nfsm_buildf_xx(mb, bpos, "uou",
  547             NFSV4OP_OPEN_CONFIRM,
  548             NFSX_V4STATEID, op->fcp->stateid,
  549             op->fcp->lop->lo_seqid);
  550 
  551         cp->seqidused = cp->req_nops++;
  552         cp->fcp = op->fcp;
  553 
  554         return (0);
  555 }
  556 
  557 /*
  558  * XXX
  559  * - Wait on recovery
  560  */
  561 int
  562 nfsm_v4build_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
  563     struct mbuf **mb, caddr_t *bpos)
  564 {
  565         struct nfs4_lowner *lop = fcp->lop;
  566 
  567         nfsm_buildf_xx(mb, bpos, "uuo",
  568             NFSV4OP_CLOSE,
  569             lop->lo_seqid,
  570             NFSX_V4STATEID, fcp->stateid);
  571 
  572         cp->seqidused = cp->req_nops++;
  573         cp->fcp = fcp;
  574 
  575         return (0);
  576 }
  577 
  578 int
  579 nfsm_v4build_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
  580     struct mbuf **mb, caddr_t *bpos)
  581 {
  582         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_ACCESS, acc->mode);
  583         cp->req_nops++;
  584 
  585         return (0);
  586 }
  587 
  588 int
  589 nfsm_v4build_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
  590     struct mbuf **mb, caddr_t *bpos)
  591 {
  592         nfsm_buildf_xx(mb, bpos, "uohu",
  593             NFSV4OP_READ,
  594             NFSX_V4STATEID, r->fcp->stateid,
  595             r->off,
  596             r->maxcnt);
  597         cp->req_nops++;
  598 
  599         return (0);
  600 }
  601 
  602 int
  603 nfsm_v4build_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
  604     struct mbuf **mb, caddr_t *bpos)
  605 {
  606         nfsm_buildf_xx(mb, bpos, "uohuu",
  607             NFSV4OP_WRITE,
  608             NFSX_V4STATEID, w->fcp->stateid,
  609             w->off,
  610             w->stable,
  611             w->cnt);
  612         cp->req_nops++;
  613         return (nfsm_uiotombuf(w->uiop, mb, w->cnt, bpos));
  614 }
  615 
  616 int
  617 nfsm_v4build_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
  618     struct mbuf **mb, caddr_t *bpos)
  619 {
  620         nfsm_buildf_xx(mb, bpos, "uhu", NFSV4OP_COMMIT, c->start, c->len);
  621         cp->req_nops++;
  622 
  623         return (0);
  624 }
  625 
  626 int
  627 nfsm_v4build_readdir_xx(struct nfs4_compound *cp, struct nfs4_oparg_readdir *r,
  628     struct mbuf **mb, caddr_t *bpos)
  629 {
  630         int i;
  631 
  632         nfsm_buildf_xx(mb, bpos, "uhouuu",
  633             NFSV4OP_READDIR,
  634             r->cookie,
  635             sizeof(r->verf), r->verf,
  636             r->cnt >> 4,        /* meaningless "dircount" field */
  637             r->cnt,
  638             r->bm->bmlen);
  639 
  640         for (i = 0; i < r->bm->bmlen; i++)
  641                 nfsm_buildf_xx(mb, bpos, "u", r->bm->bmval[i]);
  642 
  643         cp->req_nops++;
  644 
  645         return (0);
  646 }
  647 
  648 int
  649 nfsm_v4build_renew_xx(struct nfs4_compound *cp, uint64_t cid,
  650     struct mbuf **mb, caddr_t *bpos)
  651 {
  652         nfsm_buildf_xx(mb, bpos, "uh", NFSV4OP_RENEW, cid);
  653         cp->req_nops++;
  654 
  655         return (0);
  656 }
  657 
  658 int
  659 nfsm_v4build_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
  660     struct mbuf **mb, caddr_t *bpos)
  661 {
  662         uint32_t t1;
  663 
  664         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_CREATE, c->type);
  665 
  666         if (c->type == NFLNK)
  667                 /* XXX strlen */
  668                 nfsm_buildf_xx(mb, bpos, "s", strlen(c->linktext), c->linktext);
  669         else if (c->type == NFCHR || c->type == NFBLK)
  670                 nfsm_buildf_xx(mb, bpos, "uu",
  671                     umajor(c->vap->va_rdev), uminor(c->vap->va_rdev));
  672 
  673         /* Name */
  674         nfsm_buildf_xx(mb, bpos, "s", c->namelen, c->name);     
  675 
  676         /* Attributes */
  677         t1 = nfsm_v4build_attrs_xx(c->vap, mb, bpos);
  678         if (t1 != 0)
  679                 return (t1);
  680 
  681         cp->req_nops++;
  682 
  683         return (0);
  684 }
  685 
  686 int
  687 nfsm_v4build_rename_xx(struct nfs4_compound *cp, struct nfs4_oparg_rename *r,
  688     struct mbuf **mb, caddr_t *bpos)
  689 {
  690         nfsm_buildf_xx(mb, bpos, "uss", NFSV4OP_RENAME, r->fnamelen, r->fname,
  691             r->tnamelen, r->tname);
  692 
  693         cp->req_nops++;
  694 
  695         return (0);
  696 }
  697 
  698 int
  699 nfsm_v4build_link_xx(struct nfs4_compound *cp, struct nfs4_oparg_link *l,
  700     struct mbuf **mb, caddr_t *bpos)
  701 {
  702         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LINK, l->namelen, l->name);
  703 
  704         cp->req_nops++;
  705 
  706         return (0);
  707 }
  708 
  709 int
  710 nfsm_v4build_remove_xx(struct nfs4_compound *cp, const char *name, u_int namelen,
  711     struct mbuf **mb, caddr_t *bpos)
  712 {
  713         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_REMOVE, namelen, name);
  714 
  715         cp->req_nops++;
  716 
  717         return (0);
  718 }
  719 
  720 int
  721 nfsm_v4build_attrs_xx(struct vattr *vap, struct mbuf **mb, caddr_t *bpos)
  722 {
  723         uint32_t *tl, *attrlenp, *bmvalp, len;
  724         size_t siz;
  725 
  726         tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  727 
  728         *tl++ = txdr_unsigned(2);    /* bitmap length */
  729         bmvalp = tl;
  730         bzero(bmvalp, 8);
  731         tl += 2;
  732         attrlenp = tl;
  733 
  734         len = 0;
  735         if (vap->va_size != VNOVAL) {
  736                 tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  737                 FA4_SET(FA4_SIZE, bmvalp);
  738                 txdr_hyper(vap->va_size, tl); tl += 2;
  739                 len += 2 * NFSX_UNSIGNED;
  740         }
  741         if (vap->va_mode != (u_short)VNOVAL) {
  742                 tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
  743                 FA4_SET(FA4_MODE, bmvalp);
  744                 *tl++ = txdr_unsigned(vap->va_mode);
  745                 len += NFSX_UNSIGNED;
  746         }
  747         if (vap->va_uid != VNOVAL) {
  748                 int error;
  749                 char *name;
  750                 error = idmap_uid_to_name(vap->va_uid, &name, &siz);
  751                 if (error || name == NULL || siz == 0) {
  752                         /* XXX */
  753                         siz = sizeof("nobody") - 1;
  754                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, 
  755                             bpos);
  756                         *tl++ = txdr_unsigned(siz);
  757                         bcopy("nobody", tl, siz);
  758                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  759                 } else {
  760                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
  761                             bpos);
  762                         *tl++ = txdr_unsigned(siz);
  763                         bcopy(name, tl, siz);
  764                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  765                 }
  766                 FA4_SET(FA4_OWNER, bmvalp);
  767         }
  768         if (vap->va_gid != VNOVAL) {
  769                 int error;
  770                 char *name;
  771                 error = idmap_gid_to_name(vap->va_gid, &name, &siz);
  772                 if (error || name == NULL || siz == 0) {
  773                         /* XXX */
  774                         siz = sizeof("nogroup") - 1;
  775                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, 
  776                             bpos);
  777                         *tl++ = txdr_unsigned(siz);
  778                         bcopy("nogroup", tl, siz);
  779                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  780                 } else {
  781                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
  782                             bpos);
  783                         *tl++ = txdr_unsigned(siz);
  784                         bcopy(name, tl, siz);
  785                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  786                 }
  787                 FA4_SET(FA4_OWNER_GROUP, bmvalp);
  788         }
  789         if (vap->va_atime.tv_sec != VNOVAL) {
  790                 uint64_t val = vap->va_atime.tv_sec;
  791                 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  792                 FA4_SET(FA4_TIME_ACCESS_SET, bmvalp);
  793                 *tl++ = txdr_unsigned(THCLIENTTIME);
  794                 txdr_hyper(val, tl); tl += 2;
  795                 *tl++ = txdr_unsigned(vap->va_atime.tv_nsec);
  796                 len += 4 * NFSX_UNSIGNED;
  797         }
  798         if (vap->va_mtime.tv_sec != VNOVAL) {
  799                 uint64_t val = vap->va_mtime.tv_sec;
  800                 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  801                 FA4_SET(FA4_TIME_MODIFY_SET, bmvalp);
  802                 *tl++ = txdr_unsigned(THCLIENTTIME);
  803                 txdr_hyper(val, tl); tl += 2;
  804                 *tl++ = txdr_unsigned(vap->va_mtime.tv_nsec);
  805                 len += 4 * NFSX_UNSIGNED;
  806         }
  807 
  808         bmvalp[0] = txdr_unsigned(bmvalp[0]);
  809         bmvalp[1] = txdr_unsigned(bmvalp[1]);
  810 
  811         *attrlenp = txdr_unsigned(len);
  812 
  813         return (0);
  814 }
  815 
  816 int
  817 nfsm_v4dissect_compound_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
  818 {
  819         uint32_t taglen, t1, *tl;
  820 
  821         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  822         if (tl == NULL)
  823                 return (EBADRPC);
  824 
  825         /* Reply status is handled by the RPC code */
  826 
  827         taglen = fxdr_unsigned(uint32_t, *tl++);
  828         t1 = nfsm_adv_xx(nfsm_rndup(taglen), md, dpos);
  829         if (t1 != 0)
  830                 return (EBADRPC);
  831 
  832         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  833         if (tl == NULL)
  834                 return (EBADRPC);
  835 
  836         cp->rep_nops = fxdr_unsigned(uint32_t, *tl++);
  837 
  838         return (0);
  839 }
  840 
  841 int
  842 nfsm_v4dissect_simple_xx(struct nfs4_compound *cp, uint32_t op,
  843     uint32_t skipbytes, struct mbuf **md, caddr_t *dpos)
  844 {
  845         uint32_t t1, dop, status;
  846 
  847         t1 = nfsm_dissectf_xx(md, dpos, "uu", &dop, &status);
  848         if (t1 != 0)
  849                 return (t1);
  850 
  851         if (dop != op || status != 0)
  852                 return (EBADRPC);
  853 
  854         if (skipbytes > 0)
  855                 NFSM_ADV(nfsm_rndup(skipbytes));
  856 
  857         return (0);
  858 }
  859 
  860 int
  861 nfsm_v4dissect_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga,
  862     struct mbuf **md, caddr_t *dpos)
  863 {
  864         uint32_t *tl;
  865 
  866         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  867         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETATTR ||
  868             *tl++ != 0)
  869                 return (EBADRPC);
  870 
  871         return (nfsm_v4dissect_attrs_xx(&ga->fa, md, dpos));
  872 }
  873 
  874 int
  875 nfsm_v4dissect_setattr_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
  876 {
  877         uint32_t t1, op, bmlen, status;
  878 
  879         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
  880         if (t1 != 0)
  881                 return (t1);
  882 
  883         if (op != NFSV4OP_SETATTR || status != 0)
  884                 return (EBADRPC);
  885 
  886         t1 = nfsm_dissectf_xx(md, dpos, "u", &bmlen);
  887         if (t1 != 0)
  888                 return (t1);
  889 
  890         return (nfsm_dissectf_xx(md, dpos, "k", bmlen << 2));
  891 }
  892 
  893 int
  894 nfsm_v4dissect_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  895     struct mbuf **md, caddr_t *dpos)
  896 {
  897         uint32_t *tl, len, xdrlen;
  898 
  899         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  900         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETFH)
  901                 return (EBADRPC);
  902 
  903         if (*tl++ != 0)
  904                 return (EBADRPC);
  905 
  906         NFSM_DISSECT(NFSX_UNSIGNED);
  907         len = fxdr_unsigned(uint32_t, *tl++);
  908         if (len > NFSX_V4FH)
  909                 return (EBADRPC);
  910 
  911         /* XXX integrate this into nfs_mtofh()? */
  912 
  913         gfh->fh_len = len;
  914         xdrlen = nfsm_rndup(len);
  915 
  916         NFSM_DISSECT(xdrlen);
  917         bcopy(tl, &gfh->fh_val, xdrlen);
  918 
  919         return (0);
  920 }
  921 
  922 int
  923 nfsm_v4dissect_setclientid_xx(struct nfs4_compound *cp,
  924     struct nfs4_oparg_setclientid *sci, struct mbuf **md, caddr_t *dpos)
  925 {
  926         uint32_t *tl;
  927 
  928         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  929         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_SETCLIENTID)
  930                 return (EBADRPC);
  931 
  932         /* Handle NFS4ERR_CLID_INUSE specially */
  933         if (*tl++ != 0)
  934                 return (EBADRPC);
  935 
  936         NFSM_DISSECT(2 * NFSX_UNSIGNED);
  937         sci->clientid = fxdr_hyper(tl);
  938 
  939         NFSM_DISSECT(nfsm_rndup(NFSX_V4VERF));
  940         bcopy(tl, sci->verf, NFSX_V4VERF);
  941 
  942         return (0);
  943 }
  944 
  945 int
  946 nfsm_v4dissect_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
  947     struct mbuf **md, caddr_t *dpos)
  948 {
  949         uint32_t *tl, t1;
  950 
  951         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  952         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_CLOSE ||
  953             *tl++ != 0)
  954                 return (EBADRPC);
  955 
  956         /* Copy stateid */
  957         t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
  958         if (t1 != 0)
  959                 return (t1);
  960 
  961         return (0);
  962 }
  963 
  964 int
  965 nfsm_v4dissect_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
  966     struct mbuf **md, caddr_t *dpos)
  967 {
  968         uint32_t *tl;
  969 
  970         tl = nfsm_dissect_xx(4 * NFSX_UNSIGNED, md, dpos);
  971         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_ACCESS ||
  972             *tl++ != 0)
  973                 return (EBADRPC);
  974 
  975         acc->supported = fxdr_unsigned(uint32_t, *tl++);
  976         acc->rmode = fxdr_unsigned(uint32_t, *tl++);
  977 
  978         return (0);
  979 }
  980 
  981 int
  982 nfsm_v4dissect_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  983     struct mbuf **md, caddr_t *dpos)
  984 {
  985         uint32_t *tl, t1, bmlen, delegtype = ODNONE;
  986         int error = 0;
  987         nfsv4changeinfo cinfo;
  988         struct nfs4_fctx *fcp = op->fcp;
  989 
  990         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  991         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN ||
  992             *tl++ != 0)
  993                 return (EBADRPC);
  994 
  995         t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
  996         if (t1 != 0)
  997                 return (t1);
  998 
  999         error = nfsm_v4dissect_changeinfo_xx(&cinfo, md, dpos);
 1000         if (error != 0)
 1001                 goto nfsmout;
 1002 
 1003         NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1004 
 1005         op->rflags = fxdr_unsigned(uint32_t, *tl++);
 1006         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1007         if (bmlen > 2) {
 1008                 error = EBADRPC;
 1009                 goto nfsmout;
 1010         }
 1011 
 1012         /* Skip */
 1013         NFSM_ADV(nfsm_rndup(bmlen << 2));
 1014 
 1015         NFSM_DISSECT(NFSX_UNSIGNED);
 1016         delegtype = fxdr_unsigned(uint32_t, *tl++);
 1017         switch (delegtype) {
 1018         case ODREAD:
 1019         case ODWRITE:
 1020                 printf("nfs4: client delegation not yet supported\n");
 1021                 error = EOPNOTSUPP;
 1022                 goto nfsmout;
 1023                 break;
 1024         case ODNONE:
 1025         default:
 1026                 break;
 1027         }
 1028 
 1029  nfsmout:
 1030         return (error);
 1031 }
 1032 
 1033 int
 1034 nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
 1035     struct mbuf **md, caddr_t *dpos)
 1036 {
 1037         uint32_t *tl;
 1038 
 1039         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
 1040         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN_CONFIRM ||
 1041             *tl++ != 0)
 1042                 return (EBADRPC);
 1043 
 1044         return nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, op->fcp->stateid);
 1045 }
 1046 
 1047 int
 1048 nfsm_v4dissect_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
 1049     struct mbuf **md, caddr_t *dpos)
 1050 {
 1051         uint32_t op, status, t1;
 1052 
 1053         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1054         if (t1 != 0)
 1055                 return (t1);
 1056 
 1057         if (op != NFSV4OP_READ || status != 0)
 1058                 return (EBADRPC);
 1059 
 1060         t1 = nfsm_dissectf_xx(md, dpos, "uu", &r->eof, &r->retlen);
 1061         if (t1 != 0)
 1062                 return (t1);
 1063 
 1064         return (nfsm_mbuftouio(md, r->uiop, r->retlen, dpos));
 1065 }
 1066 
 1067 int
 1068 nfsm_v4dissect_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
 1069     struct mbuf **md, caddr_t *dpos)
 1070 {
 1071         uint32_t op, status, t1;
 1072 
 1073         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1074         if (t1 != 0)
 1075                 return (t1);
 1076 
 1077         if (op != NFSV4OP_WRITE || status != 0)
 1078                 return (EBADRPC);
 1079 
 1080         return (nfsm_dissectf_xx(md, dpos, "uuo", &w->retlen, &w->committed,
 1081                     NFSX_V4VERF, w->wverf));
 1082 }
 1083 
 1084 int
 1085 nfsm_v4dissect_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
 1086     struct mbuf **md, caddr_t *dpos)
 1087 {
 1088         uint32_t t1, op, status;
 1089 
 1090         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1091         if (t1 != 0)
 1092                 return (t1);
 1093 
 1094         if (op != NFSV4OP_COMMIT || status != 0)
 1095                 return (EBADRPC);
 1096 
 1097         return (nfsm_dissectf_xx(md, dpos, "o", NFSX_V4VERF, c->verf));
 1098 }
 1099 
 1100 int
 1101 nfsm_v4dissect_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
 1102     struct mbuf **md, caddr_t *dpos)
 1103 {
 1104         uint32_t t1, *tl, op, status, bmlen;
 1105         nfsv4changeinfo ci;
 1106 
 1107         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1108         if (t1 != 0)
 1109                 return (t1);
 1110 
 1111         if (op != NFSV4OP_CREATE || status != 0)
 1112                 return (EBADRPC);
 1113 
 1114         /* Just throw this away for now */
 1115         t1 = nfsm_v4dissect_changeinfo_xx(&ci, md, dpos);
 1116         if (t1 != 0)
 1117                 return (t1);
 1118 
 1119         /* Throw this away too */
 1120         NFSM_DISSECT(NFSX_UNSIGNED);
 1121         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1122         NFSM_DISSECT(bmlen * NFSX_UNSIGNED);
 1123         tl += bmlen;
 1124 
 1125         return 0;
 1126 }
 1127 
 1128 int
 1129 nfsm_v4dissect_readlink_xx(struct nfs4_compound *cp, struct uio *uiop, 
 1130     struct mbuf **md, caddr_t *dpos)
 1131 {
 1132         uint32_t t1, *tl, op, status, linklen;
 1133 
 1134         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1135         if (t1 != 0)
 1136                 return (t1);
 1137 
 1138         if (op != NFSV4OP_READLINK || status != 0)
 1139                 return (EBADRPC);
 1140 
 1141         /* Do this one manually for careful checking of sizes. */
 1142         NFSM_DISSECT(NFSX_UNSIGNED);
 1143         linklen = fxdr_unsigned(uint32_t, *tl++);
 1144         if (linklen <= 0)
 1145                 return (EBADRPC);
 1146 
 1147         return (nfsm_mbuftouio(md, uiop, MIN(linklen, uiop->uio_resid), dpos));
 1148 }
 1149 
 1150 int
 1151 nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *ci,
 1152     struct mbuf **md, caddr_t *dpos)
 1153 {
 1154         uint32_t *tl;
 1155 
 1156         NFSM_DISSECT(5 * NFSX_UNSIGNED);
 1157 
 1158         ci->ciatomic = fxdr_unsigned(uint32_t, *tl++);
 1159         ci->cibefore = fxdr_hyper(tl); tl += 2;
 1160         ci->ciafter = fxdr_hyper(tl); tl += 2;
 1161 
 1162         return (0);
 1163 }
 1164 
 1165 int
 1166 nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *fa, struct mbuf **md, caddr_t *dpos)
 1167 {
 1168         uint32_t t1, *tl, bmlen, bmval[2], attrlen, len = 0;
 1169 
 1170         /* Bitmap length + value */
 1171         NFSM_DISSECT(NFSX_UNSIGNED);
 1172 
 1173         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1174         if (bmlen > 2)
 1175                 return (EBADRPC);
 1176 
 1177         if (bmlen == 0)
 1178                 return (0);
 1179 
 1180         NFSM_DISSECT(nfsm_rndup(bmlen << 2) + NFSX_UNSIGNED);
 1181 
 1182         bmval[0] = bmlen > 0 ? fxdr_unsigned(uint32_t, *tl++) : 0;
 1183         bmval[1] = bmlen > 1 ? fxdr_unsigned(uint32_t, *tl++) : 0;
 1184 
 1185         /* Attribute length */
 1186         attrlen = fxdr_unsigned(uint32_t, *tl++);
 1187 
 1188         /*
 1189          * XXX check for correct (<=) attributes mask return from
 1190          * server.  need to pass this in.
 1191          */
 1192 
 1193         if (FA4_ISSET(FA4_TYPE, bmval)) {
 1194                 /* overflow check */
 1195                 NFSM_DISSECT(NFSX_UNSIGNED);
 1196                 fa->fa4_type = fxdr_unsigned(uint32_t, *tl++);
 1197                 fa->fa4_valid |= FA4V_TYPE;
 1198                 len += NFSX_UNSIGNED;
 1199         }
 1200         if (FA4_ISSET(FA4_CHANGE, bmval)) {
 1201                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1202                 fa->fa4_changeid = fxdr_hyper(tl);
 1203                 fa->fa4_valid |= FA4V_CHANGEID;
 1204                 len += 2 * NFSX_UNSIGNED;
 1205         }
 1206         if (FA4_ISSET(FA4_SIZE, bmval)) {
 1207                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1208                 fa->fa4_size = fxdr_hyper(tl);
 1209                 fa->fa4_valid |= FA4V_SIZE;
 1210                 len += 2 * NFSX_UNSIGNED;
 1211         }
 1212         if (FA4_ISSET(FA4_FSID, bmval)) {
 1213                 NFSM_DISSECT(4 * NFSX_UNSIGNED);
 1214                 fa->fa4_fsid_major = fxdr_hyper(tl); tl += 2;
 1215                 fa->fa4_fsid_minor = fxdr_hyper(tl);
 1216                 fa->fa4_valid |= FA4V_SIZE;
 1217                 len += 4 * NFSX_UNSIGNED;
 1218         }
 1219         if (FA4_ISSET(FA4_LEASE_TIME, bmval)) {
 1220                 NFSM_DISSECT(NFSX_UNSIGNED);
 1221                 fa->fa4_lease_time = fxdr_unsigned(uint32_t, *tl++);
 1222                 fa->fa4_valid |= FA4V_LEASE_TIME;
 1223                 len += NFSX_UNSIGNED;
 1224         }
 1225         if (FA4_ISSET(FA4_RDATTR_ERROR, bmval)) {
 1226                 /* ignore for now; we only ask for it so the compound won't fail */
 1227                 NFSM_DISSECT(NFSX_UNSIGNED);
 1228                 tl++;
 1229                 len += NFSX_UNSIGNED;
 1230         }
 1231         if (FA4_ISSET(FA4_FILEID, bmval)) {
 1232                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1233                 fa->fa4_fileid = fxdr_hyper(tl);
 1234                 fa->fa4_valid |= FA4V_FILEID;
 1235                 len += 2 * NFSX_UNSIGNED;
 1236         }
 1237         if (FA4_ISSET(FA4_FILES_FREE, bmval)) {
 1238                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1239                 fa->fa4_ffree = fxdr_hyper(tl);
 1240                 fa->fa4_valid |= FA4V_FFREE;
 1241                 len += 2 * NFSX_UNSIGNED;
 1242         }
 1243         if (FA4_ISSET(FA4_FILES_TOTAL, bmval)) {
 1244                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1245                 fa->fa4_ftotal = fxdr_hyper(tl);
 1246                 fa->fa4_valid |= FA4V_FTOTAL;
 1247                 len += 2 * NFSX_UNSIGNED;
 1248         }
 1249         if (FA4_ISSET(FA4_MAXFILESIZE, bmval)) {
 1250                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1251                 fa->fa4_maxfilesize = fxdr_hyper(tl);
 1252                 fa->fa4_valid |= FA4V_MAXFILESIZE;
 1253                 len += 2 * NFSX_UNSIGNED;
 1254         }
 1255         if (FA4_ISSET(FA4_MAXNAME, bmval)) {
 1256                 NFSM_DISSECT(NFSX_UNSIGNED);
 1257                 fa->fa4_maxname = fxdr_unsigned(uint32_t, *tl++);
 1258                 fa->fa4_valid |= FA4V_MAXNAME;
 1259                 len += NFSX_UNSIGNED;
 1260         }
 1261         if (FA4_ISSET(FA4_MAXREAD, bmval)) {
 1262                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1263                 fa->fa4_maxread = fxdr_hyper(tl);
 1264                 fa->fa4_valid |= FA4V_MAXREAD;
 1265                 len += 2 * NFSX_UNSIGNED;
 1266         }
 1267         if (FA4_ISSET(FA4_MAXWRITE, bmval)) {
 1268                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1269                 fa->fa4_maxwrite = fxdr_hyper(tl);
 1270                 fa->fa4_valid |= FA4V_MAXWRITE;
 1271                 len += 2 * NFSX_UNSIGNED;
 1272         }
 1273 
 1274         if (FA4_ISSET(FA4_MODE, bmval)) {
 1275                 NFSM_DISSECT(NFSX_UNSIGNED);
 1276                 fa->fa4_mode = fxdr_unsigned(mode_t, *tl++);
 1277                 fa->fa4_valid |= FA4V_MODE;
 1278                 len += NFSX_UNSIGNED;
 1279         }
 1280         if (FA4_ISSET(FA4_NUMLINKS, bmval)) {
 1281                 NFSM_DISSECT(NFSX_UNSIGNED);
 1282                 fa->fa4_nlink = fxdr_unsigned(nlink_t, *tl++);
 1283                 fa->fa4_valid |= FA4V_NLINK;
 1284                 len += NFSX_UNSIGNED;
 1285         }
 1286         if (FA4_ISSET(FA4_OWNER, bmval)) {
 1287                 uint32_t ownerlen;
 1288                 int error;
 1289 
 1290                 NFSM_DISSECT(NFSX_UNSIGNED);
 1291 
 1292                 ownerlen = fxdr_unsigned(uint32_t, *tl++);
 1293                 NFSM_DISSECT(nfsm_rndup(ownerlen));
 1294                 error = idmap_name_to_uid((char *)tl, ownerlen, &fa->fa4_uid);
 1295                 if (error) 
 1296                         fa->fa4_uid = -2;
 1297                 fa->fa4_valid |= FA4V_UID;
 1298                 len += NFSX_UNSIGNED + nfsm_rndup(ownerlen);
 1299         }
 1300         if (FA4_ISSET(FA4_OWNER_GROUP, bmval)) {
 1301                 uint32_t ownergrouplen;
 1302                 int error;
 1303 
 1304                 NFSM_DISSECT(NFSX_UNSIGNED);
 1305                 ownergrouplen = fxdr_unsigned(uint32_t, *tl++);
 1306                 NFSM_DISSECT(nfsm_rndup(ownergrouplen));
 1307                 error = idmap_name_to_gid((char *)tl, ownergrouplen, &fa->fa4_gid);
 1308                 if (error) 
 1309                         fa->fa4_gid = -2;
 1310                 fa->fa4_valid |= FA4V_GID;
 1311                 len += NFSX_UNSIGNED + nfsm_rndup(ownergrouplen);
 1312         }
 1313         if (FA4_ISSET(FA4_RAWDEV, bmval)) {
 1314                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1315                 fa->fa4_rdev_major = fxdr_unsigned(uint32_t, *tl++);
 1316                 fa->fa4_rdev_minor = fxdr_unsigned(uint32_t, *tl++);
 1317                 fa->fa4_valid |= FA4V_RDEV;
 1318                 len += 2 * NFSX_UNSIGNED;
 1319         }
 1320         if (FA4_ISSET(FA4_SPACE_AVAIL, bmval)) {
 1321                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1322                 fa->fa4_savail = fxdr_hyper(tl);
 1323                 fa->fa4_valid |= FA4V_SAVAIL;
 1324                 len += 2 * NFSX_UNSIGNED;
 1325         }
 1326         if (FA4_ISSET(FA4_SPACE_FREE, bmval)) {
 1327                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1328                 fa->fa4_sfree = fxdr_hyper(tl);
 1329                 fa->fa4_valid |= FA4V_SFREE;
 1330                 len += 2 * NFSX_UNSIGNED;
 1331         }
 1332         if (FA4_ISSET(FA4_SPACE_TOTAL, bmval)) {
 1333                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1334                 fa->fa4_stotal = fxdr_hyper(tl);
 1335                 fa->fa4_valid |= FA4V_STOTAL;
 1336                 len += 2 * NFSX_UNSIGNED;
 1337         }
 1338         if (FA4_ISSET(FA4_SPACE_USED, bmval)) {
 1339                 NFSM_ADV(2 * NFSX_UNSIGNED);
 1340                 len += 2 * NFSX_UNSIGNED;
 1341         }
 1342         if (FA4_ISSET(FA4_TIME_ACCESS, bmval)) {
 1343                 NFSM_MTOTIME(fa->fa4_atime);
 1344                 fa->fa4_valid |= FA4V_ATIME;
 1345                 len += 3 * NFSX_UNSIGNED;
 1346         }
 1347         if (FA4_ISSET(FA4_TIME_CREATE, bmval)) {
 1348                 NFSM_MTOTIME(fa->fa4_btime);
 1349                 fa->fa4_valid |= FA4V_BTIME;
 1350                 len += 3 * NFSX_UNSIGNED;
 1351         }
 1352         if (FA4_ISSET(FA4_TIME_METADATA, bmval)) {
 1353                 NFSM_MTOTIME(fa->fa4_ctime);
 1354                 fa->fa4_valid |= FA4V_CTIME;
 1355                 len += 3 * NFSX_UNSIGNED;
 1356         }
 1357         if (FA4_ISSET(FA4_TIME_MODIFY, bmval)) {
 1358                 NFSM_MTOTIME(fa->fa4_mtime);
 1359                 fa->fa4_valid |= FA4V_MTIME;
 1360                 len += 3 * NFSX_UNSIGNED;
 1361         }
 1362 
 1363         if (len != attrlen)
 1364                 return (EBADRPC);
 1365 
 1366         return (0);
 1367 }

Cache object: fb598cf0555e2380172882de6bcc58df


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