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

Cache object: b72f6a88568ea73f914db6cd55db860b


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