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.3 2003/07/01 18:48:31 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 __P((struct vnode *vp, u_long procid, int hsiz, 58 caddr_t *bposp)); 59 struct mbuf *nfsm_rpchead __P((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, M_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) \ 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, 1)) != 0) { \ 231 error = t1; \ 232 (f) = 0; \ 233 m_freem(mrep); \ 234 goto nfsmout; \ 235 } \ 236 (v) = ttvp; \ 237 } \ 238 } while (0) 239 240 /* Used as (f) for nfsm_wcc_data() */ 241 #define NFSV3_WCCRATTR 0 242 #define NFSV3_WCCCHK 1 243 244 #define nfsm_wcc_data(v, f) \ 245 do { \ 246 int ttattrf, ttretf = 0; \ 247 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 248 if (*tl == nfs_true) { \ 249 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \ 250 if (f) \ 251 ttretf = (VTONFS(v)->n_mtime == \ 252 fxdr_unsigned(u_int32_t, *(tl + 2))); \ 253 } \ 254 nfsm_postop_attr((v), ttattrf); \ 255 if (f) { \ 256 (f) = ttretf; \ 257 } else { \ 258 (f) = ttattrf; \ 259 } \ 260 } while (0) 261 262 /* If full is true, set all fields, otherwise just set mode and time fields */ 263 #define nfsm_v3attrbuild(a, full) \ 264 do { \ 265 if ((a)->va_mode != (mode_t)VNOVAL) { \ 266 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 267 *tl++ = nfs_true; \ 268 *tl = txdr_unsigned((a)->va_mode); \ 269 } else { \ 270 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 271 *tl = nfs_false; \ 272 } \ 273 if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \ 274 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 275 *tl++ = nfs_true; \ 276 *tl = txdr_unsigned((a)->va_uid); \ 277 } else { \ 278 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 279 *tl = nfs_false; \ 280 } \ 281 if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \ 282 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 283 *tl++ = nfs_true; \ 284 *tl = txdr_unsigned((a)->va_gid); \ 285 } else { \ 286 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 287 *tl = nfs_false; \ 288 } \ 289 if ((full) && (a)->va_size != VNOVAL) { \ 290 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 291 *tl++ = nfs_true; \ 292 txdr_hyper((a)->va_size, tl); \ 293 } else { \ 294 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 295 *tl = nfs_false; \ 296 } \ 297 if ((a)->va_atime.tv_sec != VNOVAL) { \ 298 if ((a)->va_atime.tv_sec != time_second) { \ 299 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\ 300 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\ 301 txdr_nfsv3time(&(a)->va_atime, tl); \ 302 } else { \ 303 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 304 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 305 } \ 306 } else { \ 307 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 308 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 309 } \ 310 if ((a)->va_mtime.tv_sec != VNOVAL) { \ 311 if ((a)->va_mtime.tv_sec != time_second) { \ 312 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\ 313 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\ 314 txdr_nfsv3time(&(a)->va_mtime, tl); \ 315 } else { \ 316 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 317 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 318 } \ 319 } else { \ 320 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 321 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 322 } \ 323 } while (0) 324 325 326 #define nfsm_strsiz(s,m) \ 327 do { \ 328 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 329 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \ 330 m_freem(mrep); \ 331 error = EBADRPC; \ 332 goto nfsmout; \ 333 } \ 334 } while (0) 335 336 #define nfsm_srvstrsiz(s,m) \ 337 do { \ 338 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 339 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \ 340 error = EBADRPC; \ 341 nfsm_reply(0); \ 342 } \ 343 } while (0) 344 345 #define nfsm_srvnamesiz(s) \ 346 do { \ 347 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 348 if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \ 349 error = NFSERR_NAMETOL; \ 350 if ((s) <= 0) \ 351 error = EBADRPC; \ 352 if (error) \ 353 nfsm_reply(0); \ 354 } while (0) 355 356 #define nfsm_mtouio(p,s) \ 357 do {\ 358 if ((s) > 0 && \ 359 (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \ 360 error = t1; \ 361 m_freem(mrep); \ 362 goto nfsmout; \ 363 } \ 364 } while (0) 365 366 #define nfsm_uiotom(p,s) \ 367 do { \ 368 if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \ 369 error = t1; \ 370 m_freem(mreq); \ 371 goto nfsmout; \ 372 } \ 373 } while (0) 374 375 #define nfsm_reqhead(v,a,s) \ 376 do { \ 377 mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \ 378 } while (0) 379 380 #define nfsm_reqdone \ 381 do { \ 382 m_freem(mrep); \ 383 nfsmout: \ 384 } while (0) 385 386 #define nfsm_rndup(a) (((a)+3)&(~0x3)) 387 388 #define nfsm_request(v, t, td, c) \ 389 do { \ 390 if ((error = nfs_request((v), mreq, (t), (td), \ 391 (c), &mrep, &md, &dpos)) != 0) { \ 392 if (error & NFSERR_RETERR) \ 393 error &= ~NFSERR_RETERR; \ 394 else \ 395 goto nfsmout; \ 396 } \ 397 } while (0) 398 399 #define nfsm_strtom(a,s,m) \ 400 do {\ 401 if ((s) > (m)) { \ 402 m_freem(mreq); \ 403 error = ENAMETOOLONG; \ 404 goto nfsmout; \ 405 } \ 406 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \ 407 if (t2 <= M_TRAILINGSPACE(mb)) { \ 408 nfsm_build(tl,u_int32_t *,t2); \ 409 *tl++ = txdr_unsigned(s); \ 410 *(tl+((t2>>2)-2)) = 0; \ 411 bcopy((const char *)(a), (caddr_t)tl, (s)); \ 412 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \ 413 error = t2; \ 414 m_freem(mreq); \ 415 goto nfsmout; \ 416 } \ 417 } while (0) 418 419 #define nfsm_srvdone \ 420 do { \ 421 nfsmout: \ 422 return (error); \ 423 } while (0) 424 425 #define nfsm_reply(s) \ 426 do { \ 427 nfsd->nd_repstat = error; \ 428 if (error && !(nfsd->nd_flag & ND_NFSV3)) \ 429 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 430 mrq, &mb, &bpos); \ 431 else \ 432 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 433 mrq, &mb, &bpos); \ 434 if (mrep != NULL) { \ 435 m_freem(mrep); \ 436 mrep = NULL; \ 437 } \ 438 mreq = *mrq; \ 439 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ 440 error == EBADRPC)) { \ 441 error = 0; \ 442 goto nfsmout; \ 443 } \ 444 } while (0) 445 446 #define nfsm_writereply(s, v3) \ 447 do { \ 448 nfsd->nd_repstat = error; \ 449 if (error && !(v3)) \ 450 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 451 &mreq, &mb, &bpos); \ 452 else \ 453 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 454 &mreq, &mb, &bpos); \ 455 } while (0) 456 457 #define nfsm_adv(s) \ 458 do { \ 459 t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 460 if (t1 >= (s)) { \ 461 dpos += (s); \ 462 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \ 463 error = t1; \ 464 m_freem(mrep); \ 465 goto nfsmout; \ 466 } \ 467 } while (0) 468 469 #define nfsm_srvmtofh(f) \ 470 do { \ 471 int fhlen; \ 472 if (nfsd->nd_flag & ND_NFSV3) { \ 473 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 474 fhlen = fxdr_unsigned(int, *tl); \ 475 if (fhlen != 0 && fhlen != NFSX_V3FH) { \ 476 error = EBADRPC; \ 477 nfsm_reply(0); \ 478 } \ 479 } else { \ 480 fhlen = NFSX_V2FH; \ 481 } \ 482 if (fhlen != 0) { \ 483 nfsm_dissect(tl, u_int32_t *, fhlen); \ 484 bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \ 485 } else {\ 486 bzero((caddr_t)(f), NFSX_V3FH); \ 487 } \ 488 } while (0) 489 490 #define nfsm_clget \ 491 do { \ 492 if (bp >= be) { \ 493 if (mp == mb) \ 494 mp->m_len += bp-bpos; \ 495 MGET(mp, M_WAIT, MT_DATA); \ 496 MCLGET(mp, M_WAIT); \ 497 mp->m_len = NFSMSIZ(mp); \ 498 mp2->m_next = mp; \ 499 mp2 = mp; \ 500 bp = mtod(mp, caddr_t); \ 501 be = bp+mp->m_len; \ 502 } \ 503 tl = (u_int32_t *)bp; \ 504 } while (0) 505 506 #define nfsm_srvfillattr(a, f) \ 507 do { \ 508 nfsm_srvfattr(nfsd, (a), (f)); \ 509 } while (0) 510 511 #define nfsm_srvwcc_data(br, b, ar, a) \ 512 do { \ 513 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \ 514 } while (0) 515 516 #define nfsm_srvpostop_attr(r, a) \ 517 do { \ 518 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \ 519 } while (0) 520 521 #define nfsm_srvsattr(a) \ 522 do { \ 523 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 524 if (*tl == nfs_true) { \ 525 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 526 (a)->va_mode = nfstov_mode(*tl); \ 527 } \ 528 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 529 if (*tl == nfs_true) { \ 530 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 531 (a)->va_uid = fxdr_unsigned(uid_t, *tl); \ 532 } \ 533 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 534 if (*tl == nfs_true) { \ 535 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 536 (a)->va_gid = fxdr_unsigned(gid_t, *tl); \ 537 } \ 538 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 539 if (*tl == nfs_true) { \ 540 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 541 (a)->va_size = fxdr_hyper(tl); \ 542 } \ 543 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 544 switch (fxdr_unsigned(int, *tl)) { \ 545 case NFSV3SATTRTIME_TOCLIENT: \ 546 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 547 fxdr_nfsv3time(tl, &(a)->va_atime); \ 548 break; \ 549 case NFSV3SATTRTIME_TOSERVER: \ 550 getnanotime(&(a)->va_atime); \ 551 break; \ 552 }; \ 553 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 554 switch (fxdr_unsigned(int, *tl)) { \ 555 case NFSV3SATTRTIME_TOCLIENT: \ 556 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 557 fxdr_nfsv3time(tl, &(a)->va_mtime); \ 558 break; \ 559 case NFSV3SATTRTIME_TOSERVER: \ 560 getnanotime(&(a)->va_mtime); \ 561 break; \ 562 } \ 563 } while (0) 564 565 #endif 566