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 * %sccs.include.redist.c% 9 * 10 * @(#)nfsm_subs.h 8.2 (Berkeley) 03/30/95 11 */ 12 13 14 #ifndef _NFS_NFSM_SUBS_H_ 15 #define _NFS_NFSM_SUBS_H_ 16 17 18 /* 19 * These macros do strange and peculiar things to mbuf chains for 20 * the assistance of the nfs code. To attempt to use them for any 21 * other purpose will be dangerous. (they make weird assumptions) 22 */ 23 24 /* 25 * First define what the actual subs. return 26 */ 27 extern struct mbuf *nfsm_reqh(); 28 29 #define M_HASCL(m) ((m)->m_flags & M_EXT) 30 #define NFSMINOFF(m) \ 31 if (M_HASCL(m)) \ 32 (m)->m_data = (m)->m_ext.ext_buf; \ 33 else if ((m)->m_flags & M_PKTHDR) \ 34 (m)->m_data = (m)->m_pktdat; \ 35 else \ 36 (m)->m_data = (m)->m_dat 37 #define NFSMADV(m, s) (m)->m_data += (s) 38 #define NFSMSIZ(m) ((M_HASCL(m))?MCLBYTES: \ 39 (((m)->m_flags & M_PKTHDR)?MHLEN:MLEN)) 40 41 /* 42 * Now for the macros that do the simple stuff and call the functions 43 * for the hard stuff. 44 * These macros use several vars. declared in nfsm_reqhead and these 45 * vars. must not be used elsewhere unless you are careful not to corrupt 46 * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries 47 * that may be used so long as the value is not expected to retained 48 * after a macro. 49 * I know, this is kind of dorkey, but it makes the actual op functions 50 * fairly clean and deals with the mess caused by the xdr discriminating 51 * unions. 52 */ 53 54 #define nfsm_build(a,c,s) \ 55 { if ((s) > M_TRAILINGSPACE(mb)) { \ 56 MGET(mb2, M_WAIT, MT_DATA); \ 57 if ((s) > MLEN) \ 58 panic("build > MLEN"); \ 59 mb->m_next = mb2; \ 60 mb = mb2; \ 61 mb->m_len = 0; \ 62 bpos = mtod(mb, caddr_t); \ 63 } \ 64 (a) = (c)(bpos); \ 65 mb->m_len += (s); \ 66 bpos += (s); } 67 68 #define nfsm_dissect(a, c, s) \ 69 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 70 if (t1 >= (s)) { \ 71 (a) = (c)(dpos); \ 72 dpos += (s); \ 73 } else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \ 74 error = t1; \ 75 m_freem(mrep); \ 76 goto nfsmout; \ 77 } else { \ 78 (a) = (c)cp2; \ 79 } } 80 81 #define nfsm_fhtom(v, v3) \ 82 { if (v3) { \ 83 t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \ 84 if (t2 <= M_TRAILINGSPACE(mb)) { \ 85 nfsm_build(tl, u_long *, t2); \ 86 *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \ 87 *(tl + ((t2>>2) - 2)) = 0; \ 88 bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \ 89 VTONFS(v)->n_fhsize); \ 90 } else if (t2 = nfsm_strtmbuf(&mb, &bpos, \ 91 (caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \ 92 error = t2; \ 93 m_freem(mreq); \ 94 goto nfsmout; \ 95 } \ 96 } else { \ 97 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 98 bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \ 99 } } 100 101 #define nfsm_srvfhtom(f, v3) \ 102 { if (v3) { \ 103 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \ 104 *tl++ = txdr_unsigned(NFSX_V3FH); \ 105 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 106 } else { \ 107 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 108 bcopy((caddr_t)(f), cp, NFSX_V2FH); \ 109 } } 110 111 #define nfsm_srvpostop_fh(f) \ 112 { nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \ 113 *tl++ = nfs_true; \ 114 *tl++ = txdr_unsigned(NFSX_V3FH); \ 115 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 116 } 117 118 #define nfsm_mtofh(d, v, v3, f) \ 119 { struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \ 120 if (v3) { \ 121 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 122 (f) = fxdr_unsigned(int, *tl); \ 123 } else \ 124 (f) = 1; \ 125 if (f) { \ 126 nfsm_getfh(ttfhp, ttfhsize, (v3)); \ 127 if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \ 128 &ttnp)) { \ 129 error = t1; \ 130 m_freem(mrep); \ 131 goto nfsmout; \ 132 } \ 133 (v) = NFSTOV(ttnp); \ 134 } \ 135 if (v3) { \ 136 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 137 if (f) \ 138 (f) = fxdr_unsigned(int, *tl); \ 139 else if (fxdr_unsigned(int, *tl)) \ 140 nfsm_adv(NFSX_V3FATTR); \ 141 } \ 142 if (f) \ 143 nfsm_loadattr((v), (struct vattr *)0); \ 144 } 145 146 #define nfsm_getfh(f, s, v3) \ 147 { if (v3) { \ 148 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 149 if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \ 150 (s) > NFSX_V3FHMAX) { \ 151 m_freem(mrep); \ 152 error = EBADRPC; \ 153 goto nfsmout; \ 154 } \ 155 } else \ 156 (s) = NFSX_V2FH; \ 157 nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); } 158 159 #define nfsm_loadattr(v, a) \ 160 { struct vnode *ttvp = (v); \ 161 if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \ 162 error = t1; \ 163 m_freem(mrep); \ 164 goto nfsmout; \ 165 } \ 166 (v) = ttvp; } 167 168 #define nfsm_postop_attr(v, f) \ 169 { struct vnode *ttvp = (v); \ 170 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 171 if ((f) = fxdr_unsigned(int, *tl)) { \ 172 if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \ 173 (struct vattr *)0)) { \ 174 error = t1; \ 175 (f) = 0; \ 176 m_freem(mrep); \ 177 goto nfsmout; \ 178 } \ 179 (v) = ttvp; \ 180 } } 181 182 /* Used as (f) for nfsm_wcc_data() */ 183 #define NFSV3_WCCRATTR 0 184 #define NFSV3_WCCCHK 1 185 186 #define nfsm_wcc_data(v, f) \ 187 { int ttattrf, ttretf = 0; \ 188 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 189 if (*tl == nfs_true) { \ 190 nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \ 191 if (f) \ 192 ttretf = (VTONFS(v)->n_mtime == \ 193 fxdr_unsigned(u_long, *(tl + 2))); \ 194 } \ 195 nfsm_postop_attr((v), ttattrf); \ 196 if (f) { \ 197 (f) = ttretf; \ 198 } else { \ 199 (f) = ttattrf; \ 200 } } 201 202 #define nfsm_v3sattr(s, a, u, g) \ 203 { (s)->sa_modetrue = nfs_true; \ 204 (s)->sa_mode = vtonfsv3_mode((a)->va_mode); \ 205 (s)->sa_uidtrue = nfs_true; \ 206 (s)->sa_uid = txdr_unsigned(u); \ 207 (s)->sa_gidtrue = nfs_true; \ 208 (s)->sa_gid = txdr_unsigned(g); \ 209 (s)->sa_sizefalse = nfs_false; \ 210 (s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 211 txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \ 212 (s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 213 txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \ 214 } 215 216 #define nfsm_strsiz(s,m) \ 217 { nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \ 218 if (((s) = fxdr_unsigned(long,*tl)) > (m)) { \ 219 m_freem(mrep); \ 220 error = EBADRPC; \ 221 goto nfsmout; \ 222 } } 223 224 #define nfsm_srvstrsiz(s,m) \ 225 { nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \ 226 if (((s) = fxdr_unsigned(long,*tl)) > (m) || (s) <= 0) { \ 227 error = EBADRPC; \ 228 nfsm_reply(0); \ 229 } } 230 231 #define nfsm_srvnamesiz(s) \ 232 { nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \ 233 if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \ 234 error = NFSERR_NAMETOL; \ 235 if ((s) <= 0) \ 236 error = EBADRPC; \ 237 if (error) \ 238 nfsm_reply(0); \ 239 } 240 241 #define nfsm_mtouio(p,s) \ 242 if ((s) > 0 && \ 243 (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \ 244 error = t1; \ 245 m_freem(mrep); \ 246 goto nfsmout; \ 247 } 248 249 #define nfsm_uiotom(p,s) \ 250 if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \ 251 error = t1; \ 252 m_freem(mreq); \ 253 goto nfsmout; \ 254 } 255 256 #define nfsm_reqhead(v,a,s) \ 257 mb = mreq = nfsm_reqh((v),(a),(s),&bpos) 258 259 #define nfsm_reqdone m_freem(mrep); \ 260 nfsmout: 261 262 #define nfsm_rndup(a) (((a)+3)&(~0x3)) 263 264 #define nfsm_request(v, t, p, c) \ 265 if (error = nfs_request((v), mreq, (t), (p), \ 266 (c), &mrep, &md, &dpos)) { \ 267 if (error & NFSERR_RETERR) \ 268 error &= ~NFSERR_RETERR; \ 269 else \ 270 goto nfsmout; \ 271 } 272 273 #define nfsm_strtom(a,s,m) \ 274 if ((s) > (m)) { \ 275 m_freem(mreq); \ 276 error = ENAMETOOLONG; \ 277 goto nfsmout; \ 278 } \ 279 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \ 280 if (t2 <= M_TRAILINGSPACE(mb)) { \ 281 nfsm_build(tl,u_long *,t2); \ 282 *tl++ = txdr_unsigned(s); \ 283 *(tl+((t2>>2)-2)) = 0; \ 284 bcopy((caddr_t)(a), (caddr_t)tl, (s)); \ 285 } else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \ 286 error = t2; \ 287 m_freem(mreq); \ 288 goto nfsmout; \ 289 } 290 291 #define nfsm_srvdone \ 292 nfsmout: \ 293 return(error) 294 295 #define nfsm_reply(s) \ 296 { \ 297 nfsd->nd_repstat = error; \ 298 if (error && !(nfsd->nd_flag & ND_NFSV3)) \ 299 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 300 mrq, &mb, &bpos); \ 301 else \ 302 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 303 mrq, &mb, &bpos); \ 304 m_freem(mrep); \ 305 mreq = *mrq; \ 306 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ 307 error == EBADRPC)) \ 308 return(0); \ 309 } 310 311 #define nfsm_writereply(s, v3) \ 312 { \ 313 nfsd->nd_repstat = error; \ 314 if (error && !(v3)) \ 315 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 316 &mreq, &mb, &bpos); \ 317 else \ 318 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 319 &mreq, &mb, &bpos); \ 320 } 321 322 #define nfsm_adv(s) \ 323 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 324 if (t1 >= (s)) { \ 325 dpos += (s); \ 326 } else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \ 327 error = t1; \ 328 m_freem(mrep); \ 329 goto nfsmout; \ 330 } } 331 332 #define nfsm_srvmtofh(f) \ 333 { if (nfsd->nd_flag & ND_NFSV3) { \ 334 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 335 if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \ 336 error = EBADRPC; \ 337 nfsm_reply(0); \ 338 } \ 339 } \ 340 nfsm_dissect(tl, u_long *, NFSX_V3FH); \ 341 bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \ 342 if ((nfsd->nd_flag & ND_NFSV3) == 0) \ 343 nfsm_adv(NFSX_V2FH - NFSX_V3FH); \ 344 } 345 346 #define nfsm_clget \ 347 if (bp >= be) { \ 348 if (mp == mb) \ 349 mp->m_len += bp-bpos; \ 350 MGET(mp, M_WAIT, MT_DATA); \ 351 MCLGET(mp, M_WAIT); \ 352 mp->m_len = NFSMSIZ(mp); \ 353 mp2->m_next = mp; \ 354 mp2 = mp; \ 355 bp = mtod(mp, caddr_t); \ 356 be = bp+mp->m_len; \ 357 } \ 358 tl = (u_long *)bp 359 360 #define nfsm_srvfillattr(a, f) \ 361 nfsm_srvfattr(nfsd, (a), (f)) 362 363 #define nfsm_srvwcc_data(br, b, ar, a) \ 364 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos) 365 366 #define nfsm_srvpostop_attr(r, a) \ 367 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos) 368 369 #define nfsm_srvsattr(a) \ 370 { nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 371 if (*tl == nfs_true) { \ 372 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 373 (a)->va_mode = nfstov_mode(*tl); \ 374 } \ 375 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 376 if (*tl == nfs_true) { \ 377 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 378 (a)->va_uid = fxdr_unsigned(uid_t, *tl); \ 379 } \ 380 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 381 if (*tl == nfs_true) { \ 382 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 383 (a)->va_gid = fxdr_unsigned(gid_t, *tl); \ 384 } \ 385 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 386 if (*tl == nfs_true) { \ 387 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \ 388 fxdr_hyper(tl, &(a)->va_size); \ 389 } \ 390 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 391 switch (fxdr_unsigned(int, *tl)) { \ 392 case NFSV3SATTRTIME_TOCLIENT: \ 393 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \ 394 fxdr_nfsv3time(tl, &(a)->va_atime); \ 395 break; \ 396 case NFSV3SATTRTIME_TOSERVER: \ 397 (a)->va_atime.ts_sec = time.tv_sec; \ 398 (a)->va_atime.ts_nsec = time.tv_usec * 1000; \ 399 break; \ 400 }; \ 401 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \ 402 switch (fxdr_unsigned(int, *tl)) { \ 403 case NFSV3SATTRTIME_TOCLIENT: \ 404 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \ 405 fxdr_nfsv3time(tl, &(a)->va_mtime); \ 406 break; \ 407 case NFSV3SATTRTIME_TOSERVER: \ 408 (a)->va_mtime.ts_sec = time.tv_sec; \ 409 (a)->va_mtime.ts_nsec = time.tv_usec * 1000; \ 410 break; \ 411 }; } 412 413 #endif 414