nfsm_subs.h revision 1.17
1/* $OpenBSD: nfsm_subs.h,v 1.17 2007/09/11 13:41:52 blambert 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 NFSMINOFF(m) \ 55 if (M_HASCL(m)) \ 56 (m)->m_data = (m)->m_ext.ext_buf; \ 57 else if ((m)->m_flags & M_PKTHDR) \ 58 (m)->m_data = (m)->m_pktdat; \ 59 else \ 60 (m)->m_data = (m)->m_dat 61#define NFSMADV(m, s) (m)->m_data += (s) 62#define NFSMSIZ(m) ((M_HASCL(m)) ? (m)->m_ext.ext_size : \ 63 (((m)->m_flags & M_PKTHDR) ? MHLEN : MLEN)) 64 65/* 66 * Now for the macros that do the simple stuff and call the functions 67 * for the hard stuff. 68 * These macros use several vars. declared in nfsm_reqhead and these 69 * vars. must not be used elsewhere unless you are careful not to corrupt 70 * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries 71 * that may be used so long as the value is not expected to retained 72 * after a macro. 73 * I know, this is kind of dorkey, but it makes the actual op functions 74 * fairly clean and deals with the mess caused by the xdr discriminating 75 * unions. 76 */ 77 78#define nfsm_build(a,c,s) \ 79 { if ((s) > M_TRAILINGSPACE(mb)) { \ 80 MGET(mb2, M_WAIT, MT_DATA); \ 81 if ((s) > MLEN) \ 82 panic("build > MLEN"); \ 83 mb->m_next = mb2; \ 84 mb = mb2; \ 85 mb->m_len = 0; \ 86 bpos = mtod(mb, caddr_t); \ 87 } \ 88 (a) = (c)(bpos); \ 89 mb->m_len += (s); \ 90 bpos += (s); } 91 92#define nfsm_dissect(a, c, s) \ 93 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 94 if (t1 >= (s)) { \ 95 (a) = (c)(dpos); \ 96 dpos += (s); \ 97 } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \ 98 error = t1; \ 99 m_freem(mrep); \ 100 goto nfsmout; \ 101 } else { \ 102 (a) = (c)cp2; \ 103 } } 104 105#define nfsm_fhtom(v, v3) \ 106 { if (v3) { \ 107 t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \ 108 if (t2 <= M_TRAILINGSPACE(mb)) { \ 109 nfsm_build(tl, u_int32_t *, t2); \ 110 *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \ 111 *(tl + ((t2>>2) - 2)) = 0; \ 112 bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \ 113 VTONFS(v)->n_fhsize); \ 114 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \ 115 (caddr_t)VTONFS(v)->n_fhp, \ 116 VTONFS(v)->n_fhsize)) != 0) { \ 117 error = t2; \ 118 m_freem(mreq); \ 119 goto nfsmout; \ 120 } \ 121 } else { \ 122 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 123 bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \ 124 } } 125 126#define nfsm_srvfhtom(f, v3) \ 127 { if (v3) { \ 128 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH); \ 129 *tl++ = txdr_unsigned(NFSX_V3FH); \ 130 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 131 } else { \ 132 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 133 bcopy((caddr_t)(f), cp, NFSX_V2FH); \ 134 } } 135 136#define nfsm_srvpostop_fh(f) \ 137 { nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \ 138 *tl++ = nfs_true; \ 139 *tl++ = txdr_unsigned(NFSX_V3FH); \ 140 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 141 } 142 143#define nfsm_mtofh(d, v, v3, f) \ 144 { struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \ 145 if (v3) { \ 146 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 147 (f) = fxdr_unsigned(int, *tl); \ 148 } else \ 149 (f) = 1; \ 150 if (f) { \ 151 nfsm_getfh(ttfhp, ttfhsize, (v3)); \ 152 if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \ 153 &ttnp)) != 0) { \ 154 error = t1; \ 155 m_freem(mrep); \ 156 goto nfsmout; \ 157 } \ 158 (v) = NFSTOV(ttnp); \ 159 } \ 160 if (v3) { \ 161 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 162 if (f) \ 163 (f) = fxdr_unsigned(int, *tl); \ 164 else if (fxdr_unsigned(int, *tl)) \ 165 nfsm_adv(NFSX_V3FATTR); \ 166 } \ 167 if (f) \ 168 nfsm_loadattr((v), (struct vattr *)0); \ 169 } 170 171#define nfsm_getfh(f, s, v3) \ 172 { if (v3) { \ 173 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 174 if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \ 175 (s) > NFSX_V3FHMAX) { \ 176 m_freem(mrep); \ 177 error = EBADRPC; \ 178 goto nfsmout; \ 179 } \ 180 } else \ 181 (s) = NFSX_V2FH; \ 182 nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); } 183 184#define nfsm_loadattr(v, a) \ 185 { struct vnode *ttvp = (v); \ 186 if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) != 0) { \ 187 error = t1; \ 188 m_freem(mrep); \ 189 goto nfsmout; \ 190 } \ 191 (v) = ttvp; } 192 193#define nfsm_postop_attr(v, f) \ 194 { struct vnode *ttvp = (v); \ 195 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 196 if (((f) = fxdr_unsigned(int, *tl)) != 0) { \ 197 if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \ 198 (struct vattr *)0)) != 0) { \ 199 error = t1; \ 200 (f) = 0; \ 201 m_freem(mrep); \ 202 goto nfsmout; \ 203 } \ 204 (v) = ttvp; \ 205 } } 206 207/* Used as (f) for nfsm_wcc_data() */ 208#define NFSV3_WCCRATTR 0 209#define NFSV3_WCCCHK 1 210 211#define nfsm_wcc_data(v, f) \ 212 { int ttattrf, ttretf = 0; \ 213 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 214 if (*tl == nfs_true) { \ 215 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \ 216 if (f) \ 217 ttretf = (VTONFS(v)->n_mtime == \ 218 fxdr_unsigned(u_int32_t, *(tl + 2))); \ 219 } \ 220 nfsm_postop_attr((v), ttattrf); \ 221 if (f) { \ 222 (f) = ttretf; \ 223 } else { \ 224 (f) = ttattrf; \ 225 } } 226 227/* If full is true, set all fields, otherwise just set mode and time fields */ 228#define nfsm_v3attrbuild(a, full) \ 229 { if ((a)->va_mode != (mode_t)VNOVAL) { \ 230 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 231 *tl++ = nfs_true; \ 232 *tl = txdr_unsigned((a)->va_mode); \ 233 } else { \ 234 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 235 *tl = nfs_false; \ 236 } \ 237 if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \ 238 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 239 *tl++ = nfs_true; \ 240 *tl = txdr_unsigned((a)->va_uid); \ 241 } else { \ 242 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 243 *tl = nfs_false; \ 244 } \ 245 if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \ 246 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 247 *tl++ = nfs_true; \ 248 *tl = txdr_unsigned((a)->va_gid); \ 249 } else { \ 250 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 251 *tl = nfs_false; \ 252 } \ 253 if ((full) && (a)->va_size != VNOVAL) { \ 254 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 255 *tl++ = nfs_true; \ 256 txdr_hyper((a)->va_size, tl); \ 257 } else { \ 258 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 259 *tl = nfs_false; \ 260 } \ 261 if ((a)->va_atime.tv_sec != VNOVAL) { \ 262 if ((a)->va_atime.tv_sec != time_second) { \ 263 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 264 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 265 txdr_nfsv3time(&(a)->va_atime, tl); \ 266 } else { \ 267 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 268 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 269 } \ 270 } else { \ 271 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 272 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 273 } \ 274 if ((a)->va_mtime.tv_sec != VNOVAL) { \ 275 if ((a)->va_mtime.tv_sec != time_second) { \ 276 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 277 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 278 txdr_nfsv3time(&(a)->va_mtime, tl); \ 279 } else { \ 280 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 281 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 282 } \ 283 } else { \ 284 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 285 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 286 } \ 287 } 288 289 290#define nfsm_strsiz(s,m) \ 291 { nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 292 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \ 293 m_freem(mrep); \ 294 error = EBADRPC; \ 295 goto nfsmout; \ 296 } } 297 298#define nfsm_srvstrsiz(s,m) \ 299 { nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 300 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \ 301 error = EBADRPC; \ 302 nfsm_reply(0); \ 303 } } 304 305#define nfsm_srvnamesiz(s) \ 306 { nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \ 307 if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \ 308 error = NFSERR_NAMETOL; \ 309 if ((s) <= 0) \ 310 error = EBADRPC; \ 311 if (error) \ 312 nfsm_reply(0); \ 313 } 314 315#define nfsm_mtouio(p,s) \ 316 if ((s) > 0 && \ 317 (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \ 318 error = t1; \ 319 m_freem(mrep); \ 320 goto nfsmout; \ 321 } 322 323#define nfsm_uiotom(p,s) \ 324 if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \ 325 error = t1; \ 326 m_freem(mreq); \ 327 goto nfsmout; \ 328 } 329 330#define nfsm_reqhead(v,a,s) \ 331 mb = mreq = nfsm_reqh((v),(a),(s),&bpos) 332 333#define nfsm_rndup(a) (((a)+3)&(~0x3)) 334 335#define nfsm_request(v, t, p, c) \ 336 if ((error = nfs_request((v), mreq, (t), (p), \ 337 (c), &mrep, &md, &dpos)) != 0) { \ 338 if (error & NFSERR_RETERR) \ 339 error &= ~NFSERR_RETERR; \ 340 else \ 341 goto nfsmout; \ 342 } 343 344#define nfsm_strtom(a,s,m) \ 345 if ((s) > (m)) { \ 346 m_freem(mreq); \ 347 error = ENAMETOOLONG; \ 348 goto nfsmout; \ 349 } \ 350 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \ 351 if (t2 <= M_TRAILINGSPACE(mb)) { \ 352 nfsm_build(tl,u_int32_t *,t2); \ 353 *tl++ = txdr_unsigned(s); \ 354 *(tl+((t2>>2)-2)) = 0; \ 355 bcopy((caddr_t)(a), (caddr_t)tl, (s)); \ 356 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \ 357 error = t2; \ 358 m_freem(mreq); \ 359 goto nfsmout; \ 360 } 361 362#define nfsm_reply(s) \ 363 { \ 364 nfsd->nd_repstat = error; \ 365 if (error && !(nfsd->nd_flag & ND_NFSV3)) \ 366 (void) nfs_rephead(0, nfsd, slp, error, &frev, \ 367 mrq, &mb, &bpos); \ 368 else \ 369 (void) nfs_rephead((s), nfsd, slp, error, &frev, \ 370 mrq, &mb, &bpos); \ 371 if (mrep != NULL) { \ 372 m_freem(mrep); \ 373 mrep = NULL; \ 374 } \ 375 mreq = *mrq; \ 376 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ 377 error == EBADRPC)) \ 378 return(0); \ 379 } 380 381#define nfsm_writereply(s, v3) \ 382 { \ 383 nfsd->nd_repstat = error; \ 384 if (error && !(v3)) \ 385 (void) nfs_rephead(0, nfsd, slp, error, &frev, \ 386 &mreq, &mb, &bpos); \ 387 else \ 388 (void) nfs_rephead((s), nfsd, slp, error, &frev, \ 389 &mreq, &mb, &bpos); \ 390 } 391 392#define nfsm_adv(s) \ 393 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 394 if (t1 >= (s)) { \ 395 dpos += (s); \ 396 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \ 397 error = t1; \ 398 m_freem(mrep); \ 399 goto nfsmout; \ 400 } } 401 402#define nfsm_srvmtofh(f) \ 403 { if (nfsd->nd_flag & ND_NFSV3) { \ 404 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 405 if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \ 406 error = EBADRPC; \ 407 nfsm_reply(0); \ 408 } \ 409 } \ 410 nfsm_dissect(tl, u_int32_t *, NFSX_V3FH); \ 411 bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \ 412 if ((nfsd->nd_flag & ND_NFSV3) == 0) \ 413 nfsm_adv(NFSX_V2FH - NFSX_V3FH); \ 414 } 415 416#define nfsm_clget \ 417 if (bp >= be) { \ 418 if (mp == mb) \ 419 mp->m_len += bp-bpos; \ 420 MGET(mp, M_WAIT, MT_DATA); \ 421 MCLGET(mp, M_WAIT); \ 422 mp->m_len = NFSMSIZ(mp); \ 423 mp2->m_next = mp; \ 424 mp2 = mp; \ 425 bp = mtod(mp, caddr_t); \ 426 be = bp+mp->m_len; \ 427 } \ 428 tl = (u_int32_t *)bp 429 430#define nfsm_srvfillattr(a, f) \ 431 nfsm_srvfattr(nfsd, (a), (f)) 432 433#define nfsm_srvwcc_data(br, b, ar, a) \ 434 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos) 435 436#define nfsm_srvpostop_attr(r, a) \ 437 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos) 438 439#define nfsm_srvsattr(a) \ 440 { nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 441 if (*tl == nfs_true) { \ 442 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 443 (a)->va_mode = nfstov_mode(*tl); \ 444 } \ 445 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 446 if (*tl == nfs_true) { \ 447 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 448 (a)->va_uid = fxdr_unsigned(uid_t, *tl); \ 449 } \ 450 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 451 if (*tl == nfs_true) { \ 452 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 453 (a)->va_gid = fxdr_unsigned(gid_t, *tl); \ 454 } \ 455 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 456 if (*tl == nfs_true) { \ 457 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 458 (a)->va_size = fxdr_hyper(tl); \ 459 } \ 460 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 461 switch (fxdr_unsigned(int, *tl)) { \ 462 case NFSV3SATTRTIME_TOCLIENT: \ 463 (a)->va_vaflags &= ~VA_UTIMES_NULL; \ 464 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 465 fxdr_nfsv3time(tl, &(a)->va_atime); \ 466 break; \ 467 case NFSV3SATTRTIME_TOSERVER: \ 468 getnanotime(&(a)->va_atime); \ 469 break; \ 470 }; \ 471 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 472 switch (fxdr_unsigned(int, *tl)) { \ 473 case NFSV3SATTRTIME_TOCLIENT: \ 474 (a)->va_vaflags &= ~VA_UTIMES_NULL; \ 475 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 476 fxdr_nfsv3time(tl, &(a)->va_mtime); \ 477 break; \ 478 case NFSV3SATTRTIME_TOSERVER: \ 479 getnanotime(&(a)->va_mtime); \ 480 break; \ 481 }; } 482 483#endif 484