1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95 37 * $FreeBSD: src/sys/nfs/nfsm_subs.h,v 1.27.2.1 2000/10/28 16:27:27 dwmalone Exp $ 38 * $DragonFly: src/sys/vfs/nfs/nfsm_subs.h,v 1.10 2008/09/17 21:44:25 dillon Exp $ 39 */ 40 41 42 #ifndef _NFS_NFSM_SUBS_H_ 43 #define _NFS_NFSM_SUBS_H_ 44 45 struct ucred; 46 struct vnode; 47 48 /* 49 * These macros do strange and peculiar things to mbuf chains for 50 * the assistance of the nfs code. To attempt to use them for any 51 * other purpose will be dangerous. (they make weird assumptions) 52 */ 53 54 /* 55 * First define what the actual subs. return 56 */ 57 struct mbuf *nfsm_reqh (struct vnode *vp, u_long procid, int hsiz, 58 caddr_t *bposp); 59 struct mbuf *nfsm_rpchead (struct ucred *cr, int nmflag, int procid, 60 int auth_type, int auth_len, char *auth_str, 61 int verf_len, char *verf_str, 62 struct mbuf *mrest, int mrest_len, 63 struct mbuf **mbp, u_int32_t *xidp); 64 65 #define M_HASCL(m) ((m)->m_flags & M_EXT) 66 #define NFSMINOFF(m) \ 67 do { \ 68 if (M_HASCL(m)) \ 69 (m)->m_data = (m)->m_ext.ext_buf; \ 70 else if ((m)->m_flags & M_PKTHDR) \ 71 (m)->m_data = (m)->m_pktdat; \ 72 else \ 73 (m)->m_data = (m)->m_dat; \ 74 } while (0) 75 #define NFSMADV(m, s) \ 76 do { \ 77 (m)->m_data += (s); \ 78 } while (0) 79 #define NFSMSIZ(m) ((M_HASCL(m))?MCLBYTES: \ 80 (((m)->m_flags & M_PKTHDR)?MHLEN:MLEN)) 81 82 /* 83 * Now for the macros that do the simple stuff and call the functions 84 * for the hard stuff. 85 * These macros use several vars. declared in nfsm_reqhead and these 86 * vars. must not be used elsewhere unless you are careful not to corrupt 87 * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries 88 * that may be used so long as the value is not expected to retained 89 * after a macro. 90 * I know, this is kind of dorkey, but it makes the actual op functions 91 * fairly clean and deals with the mess caused by the xdr discriminating 92 * unions. 93 */ 94 95 #define nfsm_build(a,c,s) \ 96 do { \ 97 if ((s) > M_TRAILINGSPACE(mb)) { \ 98 MGET(mb2, MB_WAIT, MT_DATA); \ 99 if ((s) > MLEN) \ 100 panic("build > MLEN"); \ 101 mb->m_next = mb2; \ 102 mb = mb2; \ 103 mb->m_len = 0; \ 104 bpos = mtod(mb, caddr_t); \ 105 } \ 106 (a) = (c)(bpos); \ 107 mb->m_len += (s); \ 108 bpos += (s); \ 109 } while (0) 110 111 #define nfsm_dissect(a, c, s) \ 112 do { \ 113 t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 114 if (t1 >= (s)) { \ 115 (a) = (c)(dpos); \ 116 dpos += (s); \ 117 } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \ 118 error = t1; \ 119 m_freem(mrep); \ 120 goto nfsmout; \ 121 } else { \ 122 (a) = (c)cp2; \ 123 } \ 124 } while (0) 125 126 #define nfsm_fhtom(v, v3) \ 127 do { \ 128 if (v3) { \ 129 t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \ 130 if (t2 <= M_TRAILINGSPACE(mb)) { \ 131 nfsm_build(tl, u_int32_t *, t2); \ 132 *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \ 133 *(tl + ((t2>>2) - 2)) = 0; \ 134 bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \ 135 VTONFS(v)->n_fhsize); \ 136 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \ 137 (caddr_t)VTONFS(v)->n_fhp, \ 138 VTONFS(v)->n_fhsize)) != 0) { \ 139 error = t2; \ 140 m_freem(mreq); \ 141 goto nfsmout; \ 142 } \ 143 } else { \ 144 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 145 bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \ 146 } \ 147 } while (0) 148 149 #define nfsm_srvfhtom(f, v3) \ 150 do { \ 151 if (v3) { \ 152 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\ 153 *tl++ = txdr_unsigned(NFSX_V3FH); \ 154 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 155 } else { \ 156 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 157 bcopy((caddr_t)(f), cp, NFSX_V2FH); \ 158 } \ 159 } while (0) 160 161 #define nfsm_srvpostop_fh(f) \ 162 do { \ 163 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \ 164 *tl++ = nfs_true; \ 165 *tl++ = txdr_unsigned(NFSX_V3FH); \ 166 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 167 } while (0) 168 169 #define nfsm_mtofh(d, v, v3, f) \ 170 do { \ 171 struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \ 172 if (v3) { \ 173 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 174 (f) = fxdr_unsigned(int, *tl); \ 175 } else \ 176 (f) = 1; \ 177 if (f) { \ 178 nfsm_getfh(ttfhp, ttfhsize, (v3)); \ 179 if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \ 180 &ttnp)) != 0) { \ 181 error = t1; \ 182 m_freem(mrep); \ 183 goto nfsmout; \ 184 } \ 185 (v) = NFSTOV(ttnp); \ 186 } \ 187 if (v3) { \ 188 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 189 if (f) \ 190 (f) = fxdr_unsigned(int, *tl); \ 191 else if (fxdr_unsigned(int, *tl)) \ 192 nfsm_adv(NFSX_V3FATTR); \ 193 } \ 194 if (f) \ 195 nfsm_loadattr((v), (struct vattr *)0); \ 196 } while (0) 197 198 #define nfsm_getfh(f, s, v3) \ 199 do { \ 200 if (v3) { \ 201 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 202 if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \ 203 (s) > NFSX_V3FHMAX) { \ 204 m_freem(mrep); \ 205 error = EBADRPC; \ 206 goto nfsmout; \ 207 } \ 208 } else \ 209 (s) = NFSX_V2FH; \ 210 nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \ 211 } while (0) 212 213 #define nfsm_loadattr(v, a) \ 214 do { \ 215 struct vnode *ttvp = (v); \ 216 if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \ 217 error = t1; \ 218 m_freem(mrep); \ 219 goto nfsmout; \ 220 } \ 221 (v) = ttvp; \ 222 } while (0) 223 224 #define nfsm_postop_attr(v, f, lflags) \ 225 do { \ 226 struct vnode *ttvp = (v); \ 227 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 228 if (((f) = fxdr_unsigned(int, *tl)) != 0) { \ 229 if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \ 230 (struct vattr *)0, lflags)) != 0) { \ 231 error = t1; \ 232 (f) = 0; \ 233 m_freem(mrep); \ 234 goto nfsmout; \ 235 } \ 236 (v) = ttvp; \ 237 } \ 238 } while (0) 239 240 /* 241 * This function updates the attribute cache based on data returned in the 242 * NFS reply for NFS RPCs that modify the target file. If the RPC succeeds 243 * a 'before' and 'after' mtime is returned that allows us to determine if 244 * the new mtime attribute represents our modification or someone else's 245 * modification. 246 * 247 * The flag argument returns non-0 if the original times matched, zero if 248 * they did not match. NRMODIFIED is automatically set if the before time 249 * does not match the original n_mtime, and n_mtime is automatically updated 250 * to the new after time (by nfsm_postop_attr()). 251 */ 252 /* Used as (f) for nfsm_wcc_data() */ 253 #define NFSV3_WCCRATTR 0 254 #define NFSV3_WCCCHK 1 255 256 #define nfsm_wcc_data(v, f) \ 257 do { \ 258 int ttattrf, ttretf = 0; \ 259 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 260 if (*tl == nfs_true) { \ 261 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \ 262 if (f) { \ 263 ttretf = (VTONFS(v)->n_mtime == \ 264 fxdr_unsigned(u_int32_t, *(tl + 2))); \ 265 if (!ttretf) \ 266 VTONFS(v)->n_flag |= NRMODIFIED; \ 267 } \ 268 nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK|NFS_LATTR_NOMTIMECHECK); \ 269 } else { \ 270 nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK); \ 271 } \ 272 if (f) { \ 273 (f) = ttretf; \ 274 } else { \ 275 (f) = ttattrf; \ 276 } \ 277 } while (0) 278 279 /* If full is true, set all fields, otherwise just set mode and time fields */ 280 #define nfsm_v3attrbuild(a, full) \ 281 do { \ 282 if ((a)->va_mode != (mode_t)VNOVAL) { \ 283 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 284 *tl++ = nfs_true; \ 285 *tl = txdr_unsigned((a)->va_mode); \ 286 } else { \ 287 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 288 *tl = nfs_false; \ 289 } \ 290 if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \ 291 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 292 *tl++ = nfs_true; \ 293 *tl = txdr_unsigned((a)->va_uid); \ 294 } else { \ 295 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 296 *tl = nfs_false; \ 297 } \ 298 if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \ 299 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 300 *tl++ = nfs_true; \ 301 *tl = txdr_unsigned((a)->va_gid); \ 302 } else { \ 303 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 304 *tl = nfs_false; \ 305 } \ 306 if ((full) && (a)->va_size != VNOVAL) { \ 307 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 308 *tl++ = nfs_true; \ 309 txdr_hyper((a)->va_size, tl); \ 310 } else { \ 311 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 312 *tl = nfs_false; \ 313 } \ 314 if ((a)->va_atime.tv_sec != VNOVAL) { \ 315 if ((a)->va_atime.tv_sec != time_second) { \ 316 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\ 317 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\ 318 txdr_nfsv3time(&(a)->va_atime, tl); \ 319 } else { \ 320 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 321 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 322 } \ 323 } else { \ 324 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 325 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 326 } \ 327 if ((a)->va_mtime.tv_sec != VNOVAL) { \ 328 if ((a)->va_mtime.tv_sec != time_second) { \ 329 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\ 330 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\ 331 txdr_nfsv3time(&(a)->va_mtime, tl); \ 332 } else { \ 333 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 334 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 335 } \ 336 } else { \ 337 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 338 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 339 } \ 340 } while (0) 341 342 343 #define nfsm_strsiz(s,m) \ 344 do { \ 345 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 346 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \ 347 m_freem(mrep); \ 348 error = EBADRPC; \ 349 goto nfsmout; \ 350 } \ 351 } while (0) 352 353 #define nfsm_srvstrsiz(s,m) \ 354 do { \ 355 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 356 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \ 357 error = EBADRPC; \ 358 nfsm_reply(0); \ 359 } \ 360 } while (0) 361 362 #define nfsm_srvnamesiz(s) \ 363 do { \ 364 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 365 if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \ 366 error = NFSERR_NAMETOL; \ 367 if ((s) <= 0) \ 368 error = EBADRPC; \ 369 if (error) \ 370 nfsm_reply(0); \ 371 } while (0) 372 373 #define nfsm_mtouio(p,s) \ 374 do {\ 375 if ((s) > 0 && \ 376 (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \ 377 error = t1; \ 378 m_freem(mrep); \ 379 goto nfsmout; \ 380 } \ 381 } while (0) 382 383 #define nfsm_uiotom(p,s) \ 384 do { \ 385 if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \ 386 error = t1; \ 387 m_freem(mreq); \ 388 goto nfsmout; \ 389 } \ 390 } while (0) 391 392 #define nfsm_reqhead(v,a,s) \ 393 do { \ 394 mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \ 395 } while (0) 396 397 #define nfsm_rndup(a) (((a)+3)&(~0x3)) 398 399 #define nfsm_request(v, t, td, c) \ 400 do { \ 401 if ((error = nfs_request((v), mreq, (t), (td), \ 402 (c), &mrep, &md, &dpos)) != 0) { \ 403 if (error & NFSERR_RETERR) \ 404 error &= ~NFSERR_RETERR; \ 405 else \ 406 goto nfsmout; \ 407 } \ 408 } while (0) 409 410 #define nfsm_strtom(a,s,m) \ 411 do {\ 412 if ((s) > (m)) { \ 413 m_freem(mreq); \ 414 error = ENAMETOOLONG; \ 415 goto nfsmout; \ 416 } \ 417 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \ 418 if (t2 <= M_TRAILINGSPACE(mb)) { \ 419 nfsm_build(tl,u_int32_t *,t2); \ 420 *tl++ = txdr_unsigned(s); \ 421 *(tl+((t2>>2)-2)) = 0; \ 422 bcopy((const char *)(a), (caddr_t)tl, (s)); \ 423 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \ 424 error = t2; \ 425 m_freem(mreq); \ 426 goto nfsmout; \ 427 } \ 428 } while (0) 429 430 #define nfsm_srvdone \ 431 do { \ 432 nfsmout: \ 433 return (error); \ 434 } while (0) 435 436 #define nfsm_reply(s) \ 437 do { \ 438 nfsd->nd_repstat = error; \ 439 if (error && !(nfsd->nd_flag & ND_NFSV3)) \ 440 nfs_rephead(0, nfsd, slp, error, mrq, &mb, &bpos); \ 441 else \ 442 nfs_rephead((s), nfsd, slp, error, mrq, &mb, &bpos); \ 443 if (mrep != NULL) { \ 444 m_freem(mrep); \ 445 mrep = NULL; \ 446 } \ 447 mreq = *mrq; \ 448 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ 449 error == EBADRPC)) { \ 450 error = 0; \ 451 goto nfsmout; \ 452 } \ 453 } while (0) 454 455 #define nfsm_writereply(s, v3) \ 456 do { \ 457 nfsd->nd_repstat = error; \ 458 if (error && !(v3)) \ 459 nfs_rephead(0, nfsd, slp, error, &mreq, &mb, &bpos); \ 460 else \ 461 nfs_rephead((s), nfsd, slp, error, &mreq, &mb, &bpos); \ 462 } while (0) 463 464 #define nfsm_adv(s) \ 465 do { \ 466 t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 467 if (t1 >= (s)) { \ 468 dpos += (s); \ 469 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \ 470 error = t1; \ 471 m_freem(mrep); \ 472 goto nfsmout; \ 473 } \ 474 } while (0) 475 476 #define nfsm_srvmtofh(f) \ 477 do { \ 478 int fhlen; \ 479 if (nfsd->nd_flag & ND_NFSV3) { \ 480 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 481 fhlen = fxdr_unsigned(int, *tl); \ 482 if (fhlen != 0 && fhlen != NFSX_V3FH) { \ 483 error = EBADRPC; \ 484 nfsm_reply(0); \ 485 } \ 486 } else { \ 487 fhlen = NFSX_V2FH; \ 488 } \ 489 if (fhlen != 0) { \ 490 nfsm_dissect(tl, u_int32_t *, fhlen); \ 491 bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \ 492 } else {\ 493 bzero((caddr_t)(f), NFSX_V3FH); \ 494 } \ 495 } while (0) 496 497 #define nfsm_clget(mp1, mp2, mb, bp, be, tl) \ 498 do { \ 499 if (bp >= be) { \ 500 if (mp1 == mb) \ 501 mp1->m_len += bp-bpos; \ 502 mp1 = m_getcl(MB_WAIT, MT_DATA, 0); \ 503 mp1->m_len = MCLBYTES; \ 504 mp2->m_next = mp1; \ 505 mp2 = mp1; \ 506 bp = mtod(mp1, caddr_t); \ 507 be = bp+mp1->m_len; \ 508 } \ 509 tl = (u_int32_t *)bp; \ 510 } while (0) 511 512 #define nfsm_srvfillattr(a, f) \ 513 do { \ 514 nfsm_srvfattr(nfsd, (a), (f)); \ 515 } while (0) 516 517 #define nfsm_srvwcc_data(br, b, ar, a) \ 518 do { \ 519 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \ 520 } while (0) 521 522 #define nfsm_srvpostop_attr(r, a) \ 523 do { \ 524 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \ 525 } while (0) 526 527 #define nfsm_srvsattr(a) \ 528 do { \ 529 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 530 if (*tl == nfs_true) { \ 531 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 532 (a)->va_mode = nfstov_mode(*tl); \ 533 } \ 534 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 535 if (*tl == nfs_true) { \ 536 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 537 (a)->va_uid = fxdr_unsigned(uid_t, *tl); \ 538 } \ 539 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 540 if (*tl == nfs_true) { \ 541 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 542 (a)->va_gid = fxdr_unsigned(gid_t, *tl); \ 543 } \ 544 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 545 if (*tl == nfs_true) { \ 546 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 547 (a)->va_size = fxdr_hyper(tl); \ 548 } \ 549 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 550 switch (fxdr_unsigned(int, *tl)) { \ 551 case NFSV3SATTRTIME_TOCLIENT: \ 552 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 553 fxdr_nfsv3time(tl, &(a)->va_atime); \ 554 break; \ 555 case NFSV3SATTRTIME_TOSERVER: \ 556 getnanotime(&(a)->va_atime); \ 557 break; \ 558 }; \ 559 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 560 switch (fxdr_unsigned(int, *tl)) { \ 561 case NFSV3SATTRTIME_TOCLIENT: \ 562 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 563 fxdr_nfsv3time(tl, &(a)->va_mtime); \ 564 break; \ 565 case NFSV3SATTRTIME_TOSERVER: \ 566 getnanotime(&(a)->va_mtime); \ 567 break; \ 568 } \ 569 } while (0) 570 571 #endif 572