procfs_validfile does have a public prototyp, but doesn't seemed to be used.
[dragonfly.git] / sys / vfs / nfs / nfsm_subs.h
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.6 2004/06/02 14:43:04 eirikn 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) \
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_rndup(a)   (((a)+3)&(~0x3))
381
382 #define nfsm_request(v, t, td, c) \
383         do { \
384                 if ((error = nfs_request((v), mreq, (t), (td), \
385                    (c), &mrep, &md, &dpos)) != 0) { \
386                         if (error & NFSERR_RETERR) \
387                                 error &= ~NFSERR_RETERR; \
388                         else \
389                                 goto nfsmout; \
390                 } \
391         } while (0)
392
393 #define nfsm_strtom(a,s,m) \
394         do {\
395                 if ((s) > (m)) { \
396                         m_freem(mreq); \
397                         error = ENAMETOOLONG; \
398                         goto nfsmout; \
399                 } \
400                 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
401                 if (t2 <= M_TRAILINGSPACE(mb)) { \
402                         nfsm_build(tl,u_int32_t *,t2); \
403                         *tl++ = txdr_unsigned(s); \
404                         *(tl+((t2>>2)-2)) = 0; \
405                         bcopy((const char *)(a), (caddr_t)tl, (s)); \
406                 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
407                         error = t2; \
408                         m_freem(mreq); \
409                         goto nfsmout; \
410                 } \
411         } while (0)
412
413 #define nfsm_srvdone \
414         do { \
415                 nfsmout: \
416                 return (error); \
417         } while (0)
418
419 #define nfsm_reply(s) \
420         do { \
421                 nfsd->nd_repstat = error; \
422                 if (error && !(nfsd->nd_flag & ND_NFSV3)) \
423                    (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
424                         mrq, &mb, &bpos); \
425                 else \
426                    (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
427                         mrq, &mb, &bpos); \
428                 if (mrep != NULL) { \
429                         m_freem(mrep); \
430                         mrep = NULL; \
431                 } \
432                 mreq = *mrq; \
433                 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
434                         error == EBADRPC)) { \
435                         error = 0; \
436                         goto nfsmout; \
437                 } \
438         } while (0)
439
440 #define nfsm_writereply(s, v3) \
441         do { \
442                 nfsd->nd_repstat = error; \
443                 if (error && !(v3)) \
444                    (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
445                         &mreq, &mb, &bpos); \
446                 else \
447                    (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
448                         &mreq, &mb, &bpos); \
449         } while (0)
450
451 #define nfsm_adv(s) \
452         do { \
453                 t1 = mtod(md, caddr_t)+md->m_len-dpos; \
454                 if (t1 >= (s)) { \
455                         dpos += (s); \
456                 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
457                         error = t1; \
458                         m_freem(mrep); \
459                         goto nfsmout; \
460                 } \
461         } while (0)
462
463 #define nfsm_srvmtofh(f) \
464         do { \
465                 int fhlen; \
466                 if (nfsd->nd_flag & ND_NFSV3) { \
467                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
468                         fhlen = fxdr_unsigned(int, *tl); \
469                         if (fhlen != 0 && fhlen != NFSX_V3FH) { \
470                                 error = EBADRPC; \
471                                 nfsm_reply(0); \
472                         } \
473                 } else { \
474                         fhlen = NFSX_V2FH; \
475                 } \
476                 if (fhlen != 0) { \
477                         nfsm_dissect(tl, u_int32_t *, fhlen); \
478                         bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
479                 } else {\
480                         bzero((caddr_t)(f), NFSX_V3FH); \
481                 } \
482         } while (0)
483
484 #define nfsm_clget \
485         do { \
486                 if (bp >= be) { \
487                         if (mp == mb) \
488                                 mp->m_len += bp-bpos; \
489                         MGET(mp, MB_WAIT, MT_DATA); \
490                         MCLGET(mp, MB_WAIT); \
491                         mp->m_len = NFSMSIZ(mp); \
492                         mp2->m_next = mp; \
493                         mp2 = mp; \
494                         bp = mtod(mp, caddr_t); \
495                         be = bp+mp->m_len; \
496                 } \
497                 tl = (u_int32_t *)bp; \
498         } while (0)
499
500 #define nfsm_srvfillattr(a, f) \
501         do { \
502                 nfsm_srvfattr(nfsd, (a), (f)); \
503         } while (0)
504
505 #define nfsm_srvwcc_data(br, b, ar, a) \
506         do { \
507                 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
508         } while (0)
509
510 #define nfsm_srvpostop_attr(r, a) \
511         do { \
512                 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
513         } while (0)
514
515 #define nfsm_srvsattr(a) \
516         do { \
517                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
518                 if (*tl == nfs_true) { \
519                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
520                         (a)->va_mode = nfstov_mode(*tl); \
521                 } \
522                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
523                 if (*tl == nfs_true) { \
524                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
525                         (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
526                 } \
527                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
528                 if (*tl == nfs_true) { \
529                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
530                         (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
531                 } \
532                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
533                 if (*tl == nfs_true) { \
534                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
535                         (a)->va_size = fxdr_hyper(tl); \
536                 } \
537                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
538                 switch (fxdr_unsigned(int, *tl)) { \
539                 case NFSV3SATTRTIME_TOCLIENT: \
540                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
541                         fxdr_nfsv3time(tl, &(a)->va_atime); \
542                         break; \
543                 case NFSV3SATTRTIME_TOSERVER: \
544                         getnanotime(&(a)->va_atime); \
545                         break; \
546                 }; \
547                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
548                 switch (fxdr_unsigned(int, *tl)) { \
549                 case NFSV3SATTRTIME_TOCLIENT: \
550                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
551                         fxdr_nfsv3time(tl, &(a)->va_mtime); \
552                         break; \
553                 case NFSV3SATTRTIME_TOSERVER: \
554                         getnanotime(&(a)->va_mtime); \
555                         break; \
556                 } \
557         } while (0)
558
559 #endif