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