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_MODIFY, __getattr_bm);
133 FA4_SET(FA4_TIME_ACCESS, __getattr_bm);
134
135 FA4_SET(FA4_TYPE, __readdir_bm);
136 FA4_SET(FA4_FSID, __readdir_bm);
137 FA4_SET(FA4_FILEID, __readdir_bm);
138 FA4_SET(FA4_RDATTR_ERROR, __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 static char zero_stateid[NFSX_V4STATEID];
425
426 nfsm_buildf_xx(mb, bpos, "uo",
427 NFSV4OP_SETATTR,
428 NFSX_V4STATEID, fcp ? fcp->stateid : zero_stateid);
429 error = nfsm_v4build_attrs_xx(vap, mb, bpos);
430 if (error == 0)
431 cp->req_nops++;
432
433 return (error);
434 }
435
436 int
437 nfsm_v4build_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
438 struct mbuf **mb, caddr_t *bpos)
439 {
440 nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_GETFH);
441
442 gfh->vp = cp->curvp;
443 cp->req_nops++;
444
445 return (0);
446 }
447
448 int
449 nfsm_v4build_lookup_xx(struct nfs4_compound *cp, struct nfs4_oparg_lookup *l,
450 struct mbuf **mb, caddr_t *bpos)
451 {
452 nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LOOKUP, l->namelen, l->name);
453
454 cp->curvp = l->vp;
455 cp->req_nops++;
456
457 return (0);
458 }
459
460 int
461 nfsm_v4build_setclientid_xx(struct nfs4_compound *cp,
462 struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
463 {
464 struct timeval tv;
465
466 microtime(&tv);
467
468 nfsm_buildf_xx(mb, bpos, "uuusussu",
469 NFSV4OP_SETCLIENTID,
470 tv.tv_sec, tv.tv_usec,
471 sci->namelen, sci->name,
472 sci->cb_prog,
473 sci->cb_netidlen, sci->cb_netid,
474 sci->cb_univaddrlen, sci->cb_univaddr,
475 0xCA11BACC);
476
477 cp->req_nops++;
478
479 return (0);
480 }
481
482 int
483 nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *cp,
484 struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
485 {
486 nfsm_buildf_xx(mb, bpos, "uho",
487 NFSV4OP_SETCLIENTID_CONFIRM,
488 sci->clientid,
489 sizeof(sci->verf), sci->verf);
490
491 cp->req_nops++;
492
493 return (0);
494 }
495
496 int
497 nfsm_v4build_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
498 struct mbuf **mb, caddr_t *bpos)
499 {
500 int error = 0;
501 struct nfs4_lowner *lop = op->fcp->lop;
502
503 nfsm_buildf_xx(mb, bpos, "uuuuhuu",
504 NFSV4OP_OPEN,
505 lop->lo_seqid,
506 op->flags & O_ACCMODE,
507 NFSV4OPENSHARE_DENY_NONE,
508 cp->nmp->nm_clientid,
509 4, lop->lo_id);
510
511 if (op->flags & O_CREAT) {
512 nfsm_buildf_xx(mb, bpos, "u", OTCREATE);
513 /* openflag4: mode */
514 nfsm_buildf_xx(mb, bpos, "u", CMUNCHECKED);
515 /* openflag4: createattrs... */
516 if (op->vap != NULL) {
517 if (op->flags & O_TRUNC)
518 op->vap->va_size = 0;
519 error = nfsm_v4build_attrs_xx(op->vap, mb, bpos);
520 if (error != 0)
521 return (error);
522 } else
523 nfsm_buildf_xx(mb, bpos, "uu", 0, 0);
524 } else
525 nfsm_buildf_xx(mb, bpos, "u", OTNOCREATE);
526
527 nfsm_buildf_xx(mb, bpos, "us", op->ctype,
528 op->cnp->cn_namelen, op->cnp->cn_nameptr);
529
530 cp->seqidused = cp->req_nops++;
531 cp->fcp = op->fcp;
532
533 return (error);
534 }
535
536 /*
537 * XXX
538 * - Wait on recovery
539 */
540 int
541 nfsm_v4build_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
542 struct mbuf **mb, caddr_t *bpos)
543 {
544 nfsm_buildf_xx(mb, bpos, "uou",
545 NFSV4OP_OPEN_CONFIRM,
546 NFSX_V4STATEID, op->fcp->stateid,
547 op->fcp->lop->lo_seqid);
548
549 cp->seqidused = cp->req_nops++;
550 cp->fcp = op->fcp;
551
552 return (0);
553 }
554
555 /*
556 * XXX
557 * - Wait on recovery
558 */
559 int
560 nfsm_v4build_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
561 struct mbuf **mb, caddr_t *bpos)
562 {
563 struct nfs4_lowner *lop = fcp->lop;
564
565 nfsm_buildf_xx(mb, bpos, "uuo",
566 NFSV4OP_CLOSE,
567 lop->lo_seqid,
568 NFSX_V4STATEID, fcp->stateid);
569
570 cp->seqidused = cp->req_nops++;
571 cp->fcp = fcp;
572
573 return (0);
574 }
575
576 int
577 nfsm_v4build_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
578 struct mbuf **mb, caddr_t *bpos)
579 {
580 nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_ACCESS, acc->mode);
581 cp->req_nops++;
582
583 return (0);
584 }
585
586 int
587 nfsm_v4build_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
588 struct mbuf **mb, caddr_t *bpos)
589 {
590 nfsm_buildf_xx(mb, bpos, "uohu",
591 NFSV4OP_READ,
592 NFSX_V4STATEID, r->fcp->stateid,
593 r->off,
594 r->maxcnt);
595 cp->req_nops++;
596
597 return (0);
598 }
599
600 int
601 nfsm_v4build_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
602 struct mbuf **mb, caddr_t *bpos)
603 {
604 nfsm_buildf_xx(mb, bpos, "uohuu",
605 NFSV4OP_WRITE,
606 NFSX_V4STATEID, w->fcp->stateid,
607 w->off,
608 w->stable,
609 w->cnt);
610 cp->req_nops++;
611 return (nfsm_uiotombuf(w->uiop, mb, w->cnt, bpos));
612 }
613
614 int
615 nfsm_v4build_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
616 struct mbuf **mb, caddr_t *bpos)
617 {
618 nfsm_buildf_xx(mb, bpos, "uhu", NFSV4OP_COMMIT, c->start, c->len);
619 cp->req_nops++;
620
621 return (0);
622 }
623
624 int
625 nfsm_v4build_readdir_xx(struct nfs4_compound *cp, struct nfs4_oparg_readdir *r,
626 struct mbuf **mb, caddr_t *bpos)
627 {
628 int i;
629
630 nfsm_buildf_xx(mb, bpos, "uhouuu",
631 NFSV4OP_READDIR,
632 r->cookie,
633 sizeof(r->verf), r->verf,
634 r->cnt >> 4, /* meaningless "dircount" field */
635 r->cnt,
636 r->bm->bmlen);
637
638 for (i = 0; i < r->bm->bmlen; i++)
639 nfsm_buildf_xx(mb, bpos, "u", r->bm->bmval[i]);
640
641 cp->req_nops++;
642
643 return (0);
644 }
645
646 int
647 nfsm_v4build_renew_xx(struct nfs4_compound *cp, uint64_t cid,
648 struct mbuf **mb, caddr_t *bpos)
649 {
650 nfsm_buildf_xx(mb, bpos, "uh", NFSV4OP_RENEW, cid);
651 cp->req_nops++;
652
653 return (0);
654 }
655
656 int
657 nfsm_v4build_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
658 struct mbuf **mb, caddr_t *bpos)
659 {
660 uint32_t t1;
661
662 nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_CREATE, c->type);
663
664 if (c->type == NFLNK)
665 /* XXX strlen */
666 nfsm_buildf_xx(mb, bpos, "s", strlen(c->linktext), c->linktext);
667 else if (c->type == NFCHR || c->type == NFBLK)
668 nfsm_buildf_xx(mb, bpos, "uu",
669 umajor(c->vap->va_rdev), uminor(c->vap->va_rdev));
670
671 /* Name */
672 nfsm_buildf_xx(mb, bpos, "s", c->namelen, c->name);
673
674 /* Attributes */
675 t1 = nfsm_v4build_attrs_xx(c->vap, mb, bpos);
676 if (t1 != 0)
677 return (t1);
678
679 cp->req_nops++;
680
681 return (0);
682 }
683
684 int
685 nfsm_v4build_rename_xx(struct nfs4_compound *cp, struct nfs4_oparg_rename *r,
686 struct mbuf **mb, caddr_t *bpos)
687 {
688 nfsm_buildf_xx(mb, bpos, "uss", NFSV4OP_RENAME, r->fnamelen, r->fname,
689 r->tnamelen, r->tname);
690
691 cp->req_nops++;
692
693 return (0);
694 }
695
696 int
697 nfsm_v4build_link_xx(struct nfs4_compound *cp, struct nfs4_oparg_link *l,
698 struct mbuf **mb, caddr_t *bpos)
699 {
700 nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LINK, l->namelen, l->name);
701
702 cp->req_nops++;
703
704 return (0);
705 }
706
707 int
708 nfsm_v4build_remove_xx(struct nfs4_compound *cp, const char *name, u_int namelen,
709 struct mbuf **mb, caddr_t *bpos)
710 {
711 nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_REMOVE, namelen, name);
712
713 cp->req_nops++;
714
715 return (0);
716 }
717
718 int
719 nfsm_v4build_attrs_xx(struct vattr *vap, struct mbuf **mb, caddr_t *bpos)
720 {
721 uint32_t *tl, *attrlenp, *bmvalp, len;
722 size_t siz;
723
724 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
725
726 *tl++ = txdr_unsigned(2); /* bitmap length */
727 bmvalp = tl;
728 bzero(bmvalp, 8);
729 tl += 2;
730 attrlenp = tl;
731
732 len = 0;
733 if (vap->va_size != VNOVAL) {
734 tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
735 FA4_SET(FA4_SIZE, bmvalp);
736 txdr_hyper(vap->va_size, tl); tl += 2;
737 len += 2 * NFSX_UNSIGNED;
738 }
739 if (vap->va_mode != (u_short)VNOVAL) {
740 tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
741 FA4_SET(FA4_MODE, bmvalp);
742 *tl++ = txdr_unsigned(vap->va_mode);
743 len += NFSX_UNSIGNED;
744 }
745 if (vap->va_uid != VNOVAL) {
746 int error;
747 char *name;
748 error = idmap_uid_to_name(vap->va_uid, &name, &siz);
749 if (error || name == NULL || siz == 0) {
750 /* XXX */
751 siz = sizeof("nobody") - 1;
752 tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
753 bpos);
754 *tl++ = txdr_unsigned(siz);
755 bcopy("nobody", tl, siz);
756 len += NFSX_UNSIGNED + nfsm_rndup(siz);
757 } else {
758 tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
759 bpos);
760 *tl++ = txdr_unsigned(siz);
761 bcopy(name, tl, siz);
762 len += NFSX_UNSIGNED + nfsm_rndup(siz);
763 }
764 FA4_SET(FA4_OWNER, bmvalp);
765 }
766 if (vap->va_gid != VNOVAL) {
767 int error;
768 char *name;
769 error = idmap_gid_to_name(vap->va_gid, &name, &siz);
770 if (error || name == NULL || siz == 0) {
771 /* XXX */
772 siz = sizeof("nogroup") - 1;
773 tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
774 bpos);
775 *tl++ = txdr_unsigned(siz);
776 bcopy("nogroup", tl, siz);
777 len += NFSX_UNSIGNED + nfsm_rndup(siz);
778 } else {
779 tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
780 bpos);
781 *tl++ = txdr_unsigned(siz);
782 bcopy(name, tl, siz);
783 len += NFSX_UNSIGNED + nfsm_rndup(siz);
784 }
785 FA4_SET(FA4_OWNER_GROUP, bmvalp);
786 }
787 if (vap->va_atime.tv_sec != VNOVAL) {
788 uint64_t val = vap->va_atime.tv_sec;
789 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
790 FA4_SET(FA4_TIME_ACCESS_SET, bmvalp);
791 *tl++ = txdr_unsigned(THCLIENTTIME);
792 txdr_hyper(val, tl); tl += 2;
793 *tl++ = txdr_unsigned(vap->va_atime.tv_nsec);
794 len += 4 * NFSX_UNSIGNED;
795 }
796 if (vap->va_mtime.tv_sec != VNOVAL) {
797 uint64_t val = vap->va_mtime.tv_sec;
798 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
799 FA4_SET(FA4_TIME_MODIFY_SET, bmvalp);
800 *tl++ = txdr_unsigned(THCLIENTTIME);
801 txdr_hyper(val, tl); tl += 2;
802 *tl++ = txdr_unsigned(vap->va_mtime.tv_nsec);
803 len += 4 * NFSX_UNSIGNED;
804 }
805
806 bmvalp[0] = txdr_unsigned(bmvalp[0]);
807 bmvalp[1] = txdr_unsigned(bmvalp[1]);
808
809 *attrlenp = txdr_unsigned(len);
810
811 return (0);
812 }
813
814 int
815 nfsm_v4dissect_compound_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
816 {
817 uint32_t taglen, t1, *tl;
818
819 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
820 if (tl == NULL)
821 return (EBADRPC);
822
823 /* Reply status is handled by the RPC code */
824
825 taglen = fxdr_unsigned(uint32_t, *tl++);
826 t1 = nfsm_adv_xx(nfsm_rndup(taglen), md, dpos);
827 if (t1 != 0)
828 return (EBADRPC);
829
830 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
831 if (tl == NULL)
832 return (EBADRPC);
833
834 cp->rep_nops = fxdr_unsigned(uint32_t, *tl++);
835
836 return (0);
837 }
838
839 int
840 nfsm_v4dissect_simple_xx(struct nfs4_compound *cp, uint32_t op,
841 uint32_t skipbytes, struct mbuf **md, caddr_t *dpos)
842 {
843 uint32_t t1, dop, status;
844
845 t1 = nfsm_dissectf_xx(md, dpos, "uu", &dop, &status);
846 if (t1 != 0)
847 return (t1);
848
849 if (dop != op || status != 0)
850 return (EBADRPC);
851
852 if (skipbytes > 0)
853 NFSM_ADV(nfsm_rndup(skipbytes));
854
855 return (0);
856 }
857
858 int
859 nfsm_v4dissect_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga,
860 struct mbuf **md, caddr_t *dpos)
861 {
862 uint32_t *tl;
863
864 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
865 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETATTR ||
866 *tl++ != 0)
867 return (EBADRPC);
868
869 return (nfsm_v4dissect_attrs_xx(&ga->fa, md, dpos));
870 }
871
872 int
873 nfsm_v4dissect_setattr_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
874 {
875 uint32_t t1, op, bmlen, status;
876
877 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
878 if (t1 != 0)
879 return (t1);
880
881 if (op != NFSV4OP_SETATTR || status != 0)
882 return (EBADRPC);
883
884 t1 = nfsm_dissectf_xx(md, dpos, "u", &bmlen);
885 if (t1 != 0)
886 return (t1);
887
888 return (nfsm_dissectf_xx(md, dpos, "k", bmlen << 2));
889 }
890
891 int
892 nfsm_v4dissect_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
893 struct mbuf **md, caddr_t *dpos)
894 {
895 uint32_t *tl, len, xdrlen;
896
897 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
898 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETFH)
899 return (EBADRPC);
900
901 if (*tl++ != 0)
902 return (EBADRPC);
903
904 NFSM_DISSECT(NFSX_UNSIGNED);
905 len = fxdr_unsigned(uint32_t, *tl++);
906 if (len > NFSX_V4FH)
907 return (EBADRPC);
908
909 /* XXX integrate this into nfs_mtofh()? */
910
911 gfh->fh_len = len;
912 xdrlen = nfsm_rndup(len);
913
914 NFSM_DISSECT(xdrlen);
915 bcopy(tl, &gfh->fh_val, xdrlen);
916
917 return (0);
918 }
919
920 int
921 nfsm_v4dissect_setclientid_xx(struct nfs4_compound *cp,
922 struct nfs4_oparg_setclientid *sci, struct mbuf **md, caddr_t *dpos)
923 {
924 uint32_t *tl;
925
926 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
927 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_SETCLIENTID)
928 return (EBADRPC);
929
930 /* Handle NFS4ERR_CLID_INUSE specially */
931 if (*tl++ != 0)
932 return (EBADRPC);
933
934 NFSM_DISSECT(2 * NFSX_UNSIGNED);
935 sci->clientid = fxdr_hyper(tl);
936
937 NFSM_DISSECT(nfsm_rndup(NFSX_V4VERF));
938 bcopy(tl, sci->verf, NFSX_V4VERF);
939
940 return (0);
941 }
942
943 int
944 nfsm_v4dissect_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
945 struct mbuf **md, caddr_t *dpos)
946 {
947 uint32_t *tl, t1;
948
949 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
950 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_CLOSE ||
951 *tl++ != 0)
952 return (EBADRPC);
953
954 /* Copy stateid */
955 t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
956 if (t1 != 0)
957 return (t1);
958
959 return (0);
960 }
961
962 int
963 nfsm_v4dissect_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
964 struct mbuf **md, caddr_t *dpos)
965 {
966 uint32_t *tl;
967
968 tl = nfsm_dissect_xx(4 * NFSX_UNSIGNED, md, dpos);
969 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_ACCESS ||
970 *tl++ != 0)
971 return (EBADRPC);
972
973 acc->supported = fxdr_unsigned(uint32_t, *tl++);
974 acc->rmode = fxdr_unsigned(uint32_t, *tl++);
975
976 return (0);
977 }
978
979 int
980 nfsm_v4dissect_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
981 struct mbuf **md, caddr_t *dpos)
982 {
983 uint32_t *tl, t1, bmlen, delegtype = ODNONE;
984 int error = 0;
985 nfsv4changeinfo cinfo;
986 struct nfs4_fctx *fcp = op->fcp;
987
988 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
989 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN ||
990 *tl++ != 0)
991 return (EBADRPC);
992
993 t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
994 if (t1 != 0)
995 return (t1);
996
997 error = nfsm_v4dissect_changeinfo_xx(&cinfo, md, dpos);
998 if (error != 0)
999 goto nfsmout;
1000
1001 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1002
1003 op->rflags = fxdr_unsigned(uint32_t, *tl++);
1004 bmlen = fxdr_unsigned(uint32_t, *tl++);
1005 if (bmlen > 2) {
1006 error = EBADRPC;
1007 goto nfsmout;
1008 }
1009
1010 /* Skip */
1011 NFSM_ADV(nfsm_rndup(bmlen << 2));
1012
1013 NFSM_DISSECT(NFSX_UNSIGNED);
1014 delegtype = fxdr_unsigned(uint32_t, *tl++);
1015 switch (delegtype) {
1016 case ODREAD:
1017 case ODWRITE:
1018 printf("nfs4: client delegation not yet supported\n");
1019 error = EOPNOTSUPP;
1020 goto nfsmout;
1021 break;
1022 case ODNONE:
1023 default:
1024 break;
1025 }
1026
1027 nfsmout:
1028 return (error);
1029 }
1030
1031 int
1032 nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
1033 struct mbuf **md, caddr_t *dpos)
1034 {
1035 uint32_t *tl;
1036
1037 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
1038 if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN_CONFIRM ||
1039 *tl++ != 0)
1040 return (EBADRPC);
1041
1042 return nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, op->fcp->stateid);
1043 }
1044
1045 int
1046 nfsm_v4dissect_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
1047 struct mbuf **md, caddr_t *dpos)
1048 {
1049 uint32_t op, status, t1;
1050
1051 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
1052 if (t1 != 0)
1053 return (t1);
1054
1055 if (op != NFSV4OP_READ || status != 0)
1056 return (EBADRPC);
1057
1058 t1 = nfsm_dissectf_xx(md, dpos, "uu", &r->eof, &r->retlen);
1059 if (t1 != 0)
1060 return (t1);
1061
1062 return (nfsm_mbuftouio(md, r->uiop, r->retlen, dpos));
1063 }
1064
1065 int
1066 nfsm_v4dissect_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
1067 struct mbuf **md, caddr_t *dpos)
1068 {
1069 uint32_t op, status, t1;
1070
1071 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
1072 if (t1 != 0)
1073 return (t1);
1074
1075 if (op != NFSV4OP_WRITE || status != 0)
1076 return (EBADRPC);
1077
1078 return (nfsm_dissectf_xx(md, dpos, "uuo", &w->retlen, &w->committed,
1079 NFSX_V4VERF, w->wverf));
1080 }
1081
1082 int
1083 nfsm_v4dissect_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
1084 struct mbuf **md, caddr_t *dpos)
1085 {
1086 uint32_t t1, op, status;
1087
1088 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
1089 if (t1 != 0)
1090 return (t1);
1091
1092 if (op != NFSV4OP_COMMIT || status != 0)
1093 return (EBADRPC);
1094
1095 return (nfsm_dissectf_xx(md, dpos, "o", NFSX_V4VERF, c->verf));
1096 }
1097
1098 int
1099 nfsm_v4dissect_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
1100 struct mbuf **md, caddr_t *dpos)
1101 {
1102 uint32_t t1, *tl, op, status, bmlen;
1103 nfsv4changeinfo ci;
1104
1105 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
1106 if (t1 != 0)
1107 return (t1);
1108
1109 if (op != NFSV4OP_CREATE || status != 0)
1110 return (EBADRPC);
1111
1112 /* Just throw this away for now */
1113 t1 = nfsm_v4dissect_changeinfo_xx(&ci, md, dpos);
1114 if (t1 != 0)
1115 return (t1);
1116
1117 /* Throw this away too */
1118 NFSM_DISSECT(NFSX_UNSIGNED);
1119 bmlen = fxdr_unsigned(uint32_t, *tl++);
1120 NFSM_DISSECT(bmlen * NFSX_UNSIGNED);
1121 tl += bmlen;
1122
1123 return 0;
1124 }
1125
1126 int
1127 nfsm_v4dissect_readlink_xx(struct nfs4_compound *cp, struct uio *uiop,
1128 struct mbuf **md, caddr_t *dpos)
1129 {
1130 uint32_t t1, *tl, op, status, linklen;
1131
1132 t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
1133 if (t1 != 0)
1134 return (t1);
1135
1136 if (op != NFSV4OP_READLINK || status != 0)
1137 return (EBADRPC);
1138
1139 /* Do this one manually for careful checking of sizes. */
1140 NFSM_DISSECT(NFSX_UNSIGNED);
1141 linklen = fxdr_unsigned(uint32_t, *tl++);
1142 if (linklen <= 0)
1143 return (EBADRPC);
1144
1145 return (nfsm_mbuftouio(md, uiop, MIN(linklen, uiop->uio_resid), dpos));
1146 }
1147
1148 int
1149 nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *ci,
1150 struct mbuf **md, caddr_t *dpos)
1151 {
1152 uint32_t *tl;
1153
1154 NFSM_DISSECT(5 * NFSX_UNSIGNED);
1155
1156 ci->ciatomic = fxdr_unsigned(uint32_t, *tl++);
1157 ci->cibefore = fxdr_hyper(tl); tl += 2;
1158 ci->ciafter = fxdr_hyper(tl); tl += 2;
1159
1160 return (0);
1161 }
1162
1163 int
1164 nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *fa, struct mbuf **md, caddr_t *dpos)
1165 {
1166 uint32_t t1, *tl, bmlen, bmval[2], attrlen, len = 0;
1167
1168 /* Bitmap length + value */
1169 NFSM_DISSECT(NFSX_UNSIGNED);
1170
1171 bmlen = fxdr_unsigned(uint32_t, *tl++);
1172 if (bmlen > 2)
1173 return (EBADRPC);
1174
1175 if (bmlen == 0)
1176 return (0);
1177
1178 NFSM_DISSECT(nfsm_rndup(bmlen << 2) + NFSX_UNSIGNED);
1179
1180 bmval[0] = bmlen > 0 ? fxdr_unsigned(uint32_t, *tl++) : 0;
1181 bmval[1] = bmlen > 1 ? fxdr_unsigned(uint32_t, *tl++) : 0;
1182
1183 /* Attribute length */
1184 attrlen = fxdr_unsigned(uint32_t, *tl++);
1185
1186 /*
1187 * XXX check for correct (<=) attributes mask return from
1188 * server. need to pass this in.
1189 */
1190
1191 if (FA4_ISSET(FA4_TYPE, bmval)) {
1192 /* overflow check */
1193 NFSM_DISSECT(NFSX_UNSIGNED);
1194 fa->fa4_type = fxdr_unsigned(uint32_t, *tl++);
1195 fa->fa4_valid |= FA4V_TYPE;
1196 len += NFSX_UNSIGNED;
1197 }
1198 if (FA4_ISSET(FA4_CHANGE, bmval)) {
1199 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1200 fa->fa4_changeid = fxdr_hyper(tl);
1201 fa->fa4_valid |= FA4V_CHANGEID;
1202 len += 2 * NFSX_UNSIGNED;
1203 }
1204 if (FA4_ISSET(FA4_SIZE, bmval)) {
1205 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1206 fa->fa4_size = fxdr_hyper(tl);
1207 fa->fa4_valid |= FA4V_SIZE;
1208 len += 2 * NFSX_UNSIGNED;
1209 }
1210 if (FA4_ISSET(FA4_FSID, bmval)) {
1211 NFSM_DISSECT(4 * NFSX_UNSIGNED);
1212 fa->fa4_fsid_major = fxdr_hyper(tl); tl += 2;
1213 fa->fa4_fsid_minor = fxdr_hyper(tl);
1214 fa->fa4_valid |= FA4V_SIZE;
1215 len += 4 * NFSX_UNSIGNED;
1216 }
1217 if (FA4_ISSET(FA4_LEASE_TIME, bmval)) {
1218 NFSM_DISSECT(NFSX_UNSIGNED);
1219 fa->fa4_lease_time = fxdr_unsigned(uint32_t, *tl++);
1220 fa->fa4_valid |= FA4V_LEASE_TIME;
1221 len += NFSX_UNSIGNED;
1222 }
1223 if (FA4_ISSET(FA4_RDATTR_ERROR, bmval)) {
1224 /* ignore for now; we only ask for it so the compound won't fail */
1225 NFSM_DISSECT(NFSX_UNSIGNED);
1226 tl++;
1227 len += NFSX_UNSIGNED;
1228 }
1229 if (FA4_ISSET(FA4_FILEID, bmval)) {
1230 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1231 fa->fa4_fileid = fxdr_hyper(tl);
1232 fa->fa4_valid |= FA4V_FILEID;
1233 len += 2 * NFSX_UNSIGNED;
1234 }
1235 if (FA4_ISSET(FA4_FILES_FREE, bmval)) {
1236 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1237 fa->fa4_ffree = fxdr_hyper(tl);
1238 fa->fa4_valid |= FA4V_FFREE;
1239 len += 2 * NFSX_UNSIGNED;
1240 }
1241 if (FA4_ISSET(FA4_FILES_TOTAL, bmval)) {
1242 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1243 fa->fa4_ftotal = fxdr_hyper(tl);
1244 fa->fa4_valid |= FA4V_FTOTAL;
1245 len += 2 * NFSX_UNSIGNED;
1246 }
1247 if (FA4_ISSET(FA4_MAXFILESIZE, bmval)) {
1248 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1249 fa->fa4_maxfilesize = fxdr_hyper(tl);
1250 fa->fa4_valid |= FA4V_MAXFILESIZE;
1251 len += 2 * NFSX_UNSIGNED;
1252 }
1253 if (FA4_ISSET(FA4_MAXNAME, bmval)) {
1254 NFSM_DISSECT(NFSX_UNSIGNED);
1255 fa->fa4_maxname = fxdr_unsigned(uint32_t, *tl++);
1256 fa->fa4_valid |= FA4V_MAXNAME;
1257 len += NFSX_UNSIGNED;
1258 }
1259 if (FA4_ISSET(FA4_MAXREAD, bmval)) {
1260 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1261 fa->fa4_maxread = fxdr_hyper(tl);
1262 fa->fa4_valid |= FA4V_MAXREAD;
1263 len += 2 * NFSX_UNSIGNED;
1264 }
1265 if (FA4_ISSET(FA4_MAXWRITE, bmval)) {
1266 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1267 fa->fa4_maxwrite = fxdr_hyper(tl);
1268 fa->fa4_valid |= FA4V_MAXWRITE;
1269 len += 2 * NFSX_UNSIGNED;
1270 }
1271
1272 if (FA4_ISSET(FA4_MODE, bmval)) {
1273 NFSM_DISSECT(NFSX_UNSIGNED);
1274 fa->fa4_mode = fxdr_unsigned(mode_t, *tl++);
1275 fa->fa4_valid |= FA4V_MODE;
1276 len += NFSX_UNSIGNED;
1277 }
1278 if (FA4_ISSET(FA4_NUMLINKS, bmval)) {
1279 NFSM_DISSECT(NFSX_UNSIGNED);
1280 fa->fa4_nlink = fxdr_unsigned(nlink_t, *tl++);
1281 fa->fa4_valid |= FA4V_NLINK;
1282 len += NFSX_UNSIGNED;
1283 }
1284 if (FA4_ISSET(FA4_OWNER, bmval)) {
1285 uint32_t ownerlen;
1286 int error;
1287
1288 NFSM_DISSECT(NFSX_UNSIGNED);
1289
1290 ownerlen = fxdr_unsigned(uint32_t, *tl++);
1291 NFSM_DISSECT(nfsm_rndup(ownerlen));
1292 error = idmap_name_to_uid((char *)tl, ownerlen, &fa->fa4_uid);
1293 if (error)
1294 fa->fa4_uid = -2;
1295 fa->fa4_valid |= FA4V_UID;
1296 len += NFSX_UNSIGNED + nfsm_rndup(ownerlen);
1297 }
1298 if (FA4_ISSET(FA4_OWNER_GROUP, bmval)) {
1299 uint32_t ownergrouplen;
1300 int error;
1301
1302 NFSM_DISSECT(NFSX_UNSIGNED);
1303 ownergrouplen = fxdr_unsigned(uint32_t, *tl++);
1304 NFSM_DISSECT(nfsm_rndup(ownergrouplen));
1305 error = idmap_name_to_gid((char *)tl, ownergrouplen, &fa->fa4_gid);
1306 if (error)
1307 fa->fa4_gid = -2;
1308 fa->fa4_valid |= FA4V_GID;
1309 len += NFSX_UNSIGNED + nfsm_rndup(ownergrouplen);
1310 }
1311 if (FA4_ISSET(FA4_RAWDEV, bmval)) {
1312 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1313 fa->fa4_rdev_major = fxdr_unsigned(uint32_t, *tl++);
1314 fa->fa4_rdev_minor = fxdr_unsigned(uint32_t, *tl++);
1315 fa->fa4_valid |= FA4V_RDEV;
1316 len += 2 * NFSX_UNSIGNED;
1317 }
1318 if (FA4_ISSET(FA4_SPACE_AVAIL, bmval)) {
1319 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1320 fa->fa4_savail = fxdr_hyper(tl);
1321 fa->fa4_valid |= FA4V_SAVAIL;
1322 len += 2 * NFSX_UNSIGNED;
1323 }
1324 if (FA4_ISSET(FA4_SPACE_FREE, bmval)) {
1325 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1326 fa->fa4_sfree = fxdr_hyper(tl);
1327 fa->fa4_valid |= FA4V_SFREE;
1328 len += 2 * NFSX_UNSIGNED;
1329 }
1330 if (FA4_ISSET(FA4_SPACE_TOTAL, bmval)) {
1331 NFSM_DISSECT(2 * NFSX_UNSIGNED);
1332 fa->fa4_stotal = fxdr_hyper(tl);
1333 fa->fa4_valid |= FA4V_STOTAL;
1334 len += 2 * NFSX_UNSIGNED;
1335 }
1336 if (FA4_ISSET(FA4_SPACE_USED, bmval)) {
1337 NFSM_ADV(2 * NFSX_UNSIGNED);
1338 len += 2 * NFSX_UNSIGNED;
1339 }
1340 if (FA4_ISSET(FA4_TIME_ACCESS, bmval)) {
1341 NFSM_MTOTIME(fa->fa4_atime);
1342 fa->fa4_valid |= FA4V_ATIME;
1343 len += 3 * NFSX_UNSIGNED;
1344 }
1345 if (FA4_ISSET(FA4_TIME_CREATE, bmval)) {
1346 NFSM_MTOTIME(fa->fa4_ctime);
1347 fa->fa4_valid |= FA4V_CTIME;
1348 len += 3 * NFSX_UNSIGNED;
1349 }
1350 if (FA4_ISSET(FA4_TIME_MODIFY, bmval)) {
1351 NFSM_MTOTIME(fa->fa4_mtime);
1352 fa->fa4_valid |= FA4V_MTIME;
1353 len += 3 * NFSX_UNSIGNED;
1354 }
1355
1356 if (len != attrlen)
1357 return (EBADRPC);
1358
1359 return (0);
1360 }
Cache object: 90d19353221b2d53141d8bea8f9be1b0
|