nfs_serv.c revision 1.75 1 /* $NetBSD: nfs_serv.c,v 1.75 2003/05/29 15:18:14 yamt Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
39 */
40
41 /*
42 * nfs version 2 and 3 server calls to vnode ops
43 * - these routines generally have 3 phases
44 * 1 - break down and validate rpc request in mbuf list
45 * 2 - do the vnode ops for the request
46 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
47 * 3 - build the rpc reply in an mbuf list
48 * nb:
49 * - do not mix the phases, since the nfsm_?? macros can return failures
50 * on a bad rpc or similar and do not do any vrele() or vput()'s
51 *
52 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
53 * error number iff error != 0 whereas
54 * returning an error from the server function implies a fatal error
55 * such as a badly constructed rpc request that should be dropped without
56 * a reply.
57 * For Version 3, nfsm_reply() does not return for the error case, since
58 * most version 3 rpcs return more than the status for error cases.
59 */
60
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.75 2003/05/29 15:18:14 yamt Exp $");
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/proc.h>
67 #include <sys/file.h>
68 #include <sys/namei.h>
69 #include <sys/vnode.h>
70 #include <sys/mount.h>
71 #include <sys/socket.h>
72 #include <sys/socketvar.h>
73 #include <sys/mbuf.h>
74 #include <sys/dirent.h>
75 #include <sys/stat.h>
76 #include <sys/kernel.h>
77 #include <ufs/ufs/dir.h>
78
79 #include <uvm/uvm.h>
80
81 #include <nfs/nfsproto.h>
82 #include <nfs/rpcv2.h>
83 #include <nfs/nfs.h>
84 #include <nfs/xdr_subs.h>
85 #include <nfs/nfsm_subs.h>
86 #include <nfs/nqnfs.h>
87 #include <nfs/nfs_var.h>
88
89 /* Global vars */
90 extern u_int32_t nfs_xdrneg1;
91 extern u_int32_t nfs_false, nfs_true;
92 extern enum vtype nv3tov_type[8];
93 extern struct nfsstats nfsstats;
94 extern const nfstype nfsv2_type[9];
95 extern const nfstype nfsv3_type[9];
96 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
97 int nfsd_use_loan = 1; /* use page-loan for READ OP */
98
99 /*
100 * nfs v3 access service
101 */
102 int
103 nfsrv3_access(nfsd, slp, procp, mrq)
104 struct nfsrv_descript *nfsd;
105 struct nfssvc_sock *slp;
106 struct proc *procp;
107 struct mbuf **mrq;
108 {
109 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
110 struct mbuf *nam = nfsd->nd_nam;
111 caddr_t dpos = nfsd->nd_dpos;
112 struct ucred *cred = &nfsd->nd_cr;
113 struct vnode *vp;
114 nfsfh_t nfh;
115 fhandle_t *fhp;
116 u_int32_t *tl;
117 int32_t t1;
118 caddr_t bpos;
119 int error = 0, rdonly, cache = 0, getret;
120 char *cp2;
121 struct mbuf *mb, *mreq;
122 struct vattr va;
123 u_long inmode, testmode, outmode;
124 u_quad_t frev;
125
126 fhp = &nfh.fh_generic;
127 nfsm_srvmtofh(fhp);
128 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
129 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
130 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
131 if (error) {
132 nfsm_reply(NFSX_UNSIGNED);
133 nfsm_srvpostop_attr(1, (struct vattr *)0);
134 return (0);
135 }
136 inmode = fxdr_unsigned(u_int32_t, *tl);
137 outmode = 0;
138 if ((inmode & NFSV3ACCESS_READ) &&
139 nfsrv_access(vp, VREAD, cred, rdonly, procp, 0) == 0)
140 outmode |= NFSV3ACCESS_READ;
141 if (vp->v_type != VDIR) {
142 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
143 if (testmode &&
144 nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
145 outmode |= testmode;
146 if ((inmode & NFSV3ACCESS_EXECUTE) &&
147 nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
148 outmode |= NFSV3ACCESS_EXECUTE;
149 } else {
150 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
151 NFSV3ACCESS_DELETE);
152 if (testmode &&
153 nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
154 outmode |= testmode;
155 if ((inmode & NFSV3ACCESS_LOOKUP) &&
156 nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
157 outmode |= NFSV3ACCESS_LOOKUP;
158 }
159 getret = VOP_GETATTR(vp, &va, cred, procp);
160 vput(vp);
161 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
162 nfsm_srvpostop_attr(getret, &va);
163 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
164 *tl = txdr_unsigned(outmode);
165 nfsm_srvdone;
166 }
167
168 /*
169 * nfs getattr service
170 */
171 int
172 nfsrv_getattr(nfsd, slp, procp, mrq)
173 struct nfsrv_descript *nfsd;
174 struct nfssvc_sock *slp;
175 struct proc *procp;
176 struct mbuf **mrq;
177 {
178 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
179 struct mbuf *nam = nfsd->nd_nam;
180 caddr_t dpos = nfsd->nd_dpos;
181 struct ucred *cred = &nfsd->nd_cr;
182 struct nfs_fattr *fp;
183 struct vattr va;
184 struct vnode *vp;
185 nfsfh_t nfh;
186 fhandle_t *fhp;
187 u_int32_t *tl;
188 int32_t t1;
189 caddr_t bpos;
190 int error = 0, rdonly, cache;
191 char *cp2;
192 struct mbuf *mb, *mreq;
193 u_quad_t frev;
194
195 fhp = &nfh.fh_generic;
196 nfsm_srvmtofh(fhp);
197 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
198 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
199 if (error) {
200 nfsm_reply(0);
201 return (0);
202 }
203 nqsrv_getl(vp, ND_READ);
204 error = VOP_GETATTR(vp, &va, cred, procp);
205 vput(vp);
206 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
207 if (error)
208 return (0);
209 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
210 nfsm_srvfillattr(&va, fp);
211 nfsm_srvdone;
212 }
213
214 /*
215 * nfs setattr service
216 */
217 int
218 nfsrv_setattr(nfsd, slp, procp, mrq)
219 struct nfsrv_descript *nfsd;
220 struct nfssvc_sock *slp;
221 struct proc *procp;
222 struct mbuf **mrq;
223 {
224 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
225 struct mbuf *nam = nfsd->nd_nam;
226 caddr_t dpos = nfsd->nd_dpos;
227 struct ucred *cred = &nfsd->nd_cr;
228 struct vattr va, preat;
229 struct nfsv2_sattr *sp;
230 struct nfs_fattr *fp;
231 struct vnode *vp;
232 nfsfh_t nfh;
233 fhandle_t *fhp;
234 u_int32_t *tl;
235 int32_t t1;
236 caddr_t bpos;
237 int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
238 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
239 char *cp2;
240 struct mbuf *mb, *mreq;
241 u_quad_t frev;
242 struct timespec guard;
243
244 fhp = &nfh.fh_generic;
245 nfsm_srvmtofh(fhp);
246 VATTR_NULL(&va);
247 if (v3) {
248 nfsm_srvsattr(&va);
249 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
250 gcheck = fxdr_unsigned(int, *tl);
251 if (gcheck) {
252 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
253 fxdr_nfsv3time(tl, &guard);
254 }
255 } else {
256 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
257 /*
258 * Nah nah nah nah na nah
259 * There is a bug in the Sun client that puts 0xffff in the mode
260 * field of sattr when it should put in 0xffffffff. The u_short
261 * doesn't sign extend.
262 * --> check the low order 2 bytes for 0xffff
263 */
264 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
265 va.va_mode = nfstov_mode(sp->sa_mode);
266 if (sp->sa_uid != nfs_xdrneg1)
267 va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
268 if (sp->sa_gid != nfs_xdrneg1)
269 va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
270 if (sp->sa_size != nfs_xdrneg1)
271 va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
272 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
273 #ifdef notyet
274 fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
275 #else
276 va.va_atime.tv_sec =
277 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
278 va.va_atime.tv_nsec = 0;
279 #endif
280 }
281 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
282 fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
283
284 }
285
286 /*
287 * Now that we have all the fields, lets do it.
288 */
289 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
290 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
291 if (error) {
292 nfsm_reply(2 * NFSX_UNSIGNED);
293 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
294 return (0);
295 }
296 nqsrv_getl(vp, ND_WRITE);
297 if (v3) {
298 error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
299 if (!error && gcheck &&
300 (preat.va_ctime.tv_sec != guard.tv_sec ||
301 preat.va_ctime.tv_nsec != guard.tv_nsec))
302 error = NFSERR_NOT_SYNC;
303 if (error) {
304 vput(vp);
305 nfsm_reply(NFSX_WCCDATA(v3));
306 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
307 return (0);
308 }
309 }
310
311 /*
312 * If the size is being changed write acces is required, otherwise
313 * just check for a read only file system.
314 */
315 if (va.va_size == ((u_quad_t)((quad_t) -1))) {
316 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
317 error = EROFS;
318 goto out;
319 }
320 } else {
321 if (vp->v_type == VDIR) {
322 error = EISDIR;
323 goto out;
324 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
325 procp, 0)) != 0)
326 goto out;
327 }
328 error = VOP_SETATTR(vp, &va, cred, procp);
329 postat_ret = VOP_GETATTR(vp, &va, cred, procp);
330 if (!error)
331 error = postat_ret;
332 out:
333 vput(vp);
334 nfsm_reply(NFSX_WCCORFATTR(v3));
335 if (v3) {
336 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
337 return (0);
338 } else {
339 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
340 nfsm_srvfillattr(&va, fp);
341 }
342 nfsm_srvdone;
343 }
344
345 /*
346 * nfs lookup rpc
347 */
348 int
349 nfsrv_lookup(nfsd, slp, procp, mrq)
350 struct nfsrv_descript *nfsd;
351 struct nfssvc_sock *slp;
352 struct proc *procp;
353 struct mbuf **mrq;
354 {
355 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
356 struct mbuf *nam = nfsd->nd_nam;
357 caddr_t dpos = nfsd->nd_dpos;
358 struct ucred *cred = &nfsd->nd_cr;
359 struct nfs_fattr *fp;
360 struct nameidata nd, ind, *ndp = &nd;
361 struct vnode *vp, *dirp;
362 nfsfh_t nfh;
363 fhandle_t *fhp;
364 caddr_t cp;
365 u_int32_t *tl;
366 int32_t t1;
367 caddr_t bpos;
368 int error = 0, cache, dirattr_ret = 1;
369 uint32_t len;
370 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
371 char *cp2;
372 struct mbuf *mb, *mreq;
373 struct vattr va, dirattr;
374 u_quad_t frev;
375
376 fhp = &nfh.fh_generic;
377 nfsm_srvmtofh(fhp);
378 nfsm_srvnamesiz(len);
379
380 pubflag = nfs_ispublicfh(fhp);
381
382 nd.ni_cnd.cn_cred = cred;
383 nd.ni_cnd.cn_nameiop = LOOKUP;
384 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
385 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
386 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
387
388 if (!error && pubflag) {
389 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
390 /*
391 * Setup call to lookup() to see if we can find
392 * the index file. Arguably, this doesn't belong
393 * in a kernel.. Ugh.
394 */
395 ind = nd;
396 VOP_UNLOCK(nd.ni_vp, 0);
397 ind.ni_pathlen = strlen(nfs_pub.np_index);
398 ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
399 nfs_pub.np_index;
400 ind.ni_startdir = nd.ni_vp;
401 VREF(ind.ni_startdir);
402 error = lookup(&ind);
403 if (!error) {
404 /*
405 * Found an index file. Get rid of
406 * the old references.
407 */
408 if (dirp)
409 vrele(dirp);
410 dirp = nd.ni_vp;
411 vrele(nd.ni_startdir);
412 ndp = &ind;
413 } else
414 error = 0;
415 }
416 /*
417 * If the public filehandle was used, check that this lookup
418 * didn't result in a filehandle outside the publicly exported
419 * filesystem.
420 */
421
422 if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
423 vput(nd.ni_vp);
424 error = EPERM;
425 }
426 }
427
428 if (dirp) {
429 if (v3)
430 dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
431 procp);
432 vrele(dirp);
433 }
434
435 if (error) {
436 nfsm_reply(NFSX_POSTOPATTR(v3));
437 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
438 return (0);
439 }
440
441 nqsrv_getl(ndp->ni_startdir, ND_READ);
442 vrele(ndp->ni_startdir);
443 PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
444 vp = ndp->ni_vp;
445 memset((caddr_t)fhp, 0, sizeof(nfh));
446 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
447 error = VFS_VPTOFH(vp, &fhp->fh_fid);
448 if (!error)
449 error = VOP_GETATTR(vp, &va, cred, procp);
450 vput(vp);
451 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
452 if (error) {
453 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
454 return (0);
455 }
456 nfsm_srvfhtom(fhp, v3);
457 if (v3) {
458 nfsm_srvpostop_attr(0, &va);
459 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
460 } else {
461 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
462 nfsm_srvfillattr(&va, fp);
463 }
464 nfsm_srvdone;
465 }
466
467 /*
468 * nfs readlink service
469 */
470 int
471 nfsrv_readlink(nfsd, slp, procp, mrq)
472 struct nfsrv_descript *nfsd;
473 struct nfssvc_sock *slp;
474 struct proc *procp;
475 struct mbuf **mrq;
476 {
477 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
478 struct mbuf *nam = nfsd->nd_nam;
479 caddr_t dpos = nfsd->nd_dpos;
480 struct ucred *cred = &nfsd->nd_cr;
481 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
482 struct iovec *ivp = iv;
483 struct mbuf *mp;
484 u_int32_t *tl;
485 int32_t t1;
486 caddr_t bpos;
487 int error = 0, rdonly, cache, i, tlen, len, getret;
488 int v3 = (nfsd->nd_flag & ND_NFSV3);
489 char *cp2;
490 struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq;
491 struct vnode *vp;
492 struct vattr attr;
493 nfsfh_t nfh;
494 fhandle_t *fhp;
495 struct uio io, *uiop = &io;
496 u_quad_t frev;
497
498 fhp = &nfh.fh_generic;
499 nfsm_srvmtofh(fhp);
500 len = 0;
501 i = 0;
502 while (len < NFS_MAXPATHLEN) {
503 mp = m_get(M_WAIT, MT_DATA);
504 MCLAIM(mp, &nfs_mowner);
505 m_clget(mp, M_WAIT);
506 mp->m_len = NFSMSIZ(mp);
507 if (len == 0)
508 mp3 = mp2 = mp;
509 else {
510 mp2->m_next = mp;
511 mp2 = mp;
512 }
513 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
514 mp->m_len = NFS_MAXPATHLEN-len;
515 len = NFS_MAXPATHLEN;
516 } else
517 len += mp->m_len;
518 ivp->iov_base = mtod(mp, caddr_t);
519 ivp->iov_len = mp->m_len;
520 i++;
521 ivp++;
522 }
523 uiop->uio_iov = iv;
524 uiop->uio_iovcnt = i;
525 uiop->uio_offset = 0;
526 uiop->uio_resid = len;
527 uiop->uio_rw = UIO_READ;
528 uiop->uio_segflg = UIO_SYSSPACE;
529 uiop->uio_procp = (struct proc *)0;
530 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
531 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
532 if (error) {
533 m_freem(mp3);
534 nfsm_reply(2 * NFSX_UNSIGNED);
535 nfsm_srvpostop_attr(1, (struct vattr *)0);
536 return (0);
537 }
538 if (vp->v_type != VLNK) {
539 if (v3)
540 error = EINVAL;
541 else
542 error = ENXIO;
543 goto out;
544 }
545 nqsrv_getl(vp, ND_READ);
546 error = VOP_READLINK(vp, uiop, cred);
547 out:
548 getret = VOP_GETATTR(vp, &attr, cred, procp);
549 vput(vp);
550 if (error)
551 m_freem(mp3);
552 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
553 if (v3) {
554 nfsm_srvpostop_attr(getret, &attr);
555 if (error)
556 return (0);
557 }
558 if (uiop->uio_resid > 0) {
559 len -= uiop->uio_resid;
560 tlen = nfsm_rndup(len);
561 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
562 }
563 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
564 *tl = txdr_unsigned(len);
565 mb->m_next = mp3;
566 nfsm_srvdone;
567 }
568
569 /*
570 * XXX UBC temp limit
571 * maximum number of pages we can do VOP_GETPAGES and loan-out at once.
572 * should be <= MAX_READ_AHEAD in genfs_vnops.c
573 */
574 #define NFSD_READ_GETPAGES_CHUNK 16
575
576 /*
577 * nfs read service
578 */
579 int
580 nfsrv_read(nfsd, slp, procp, mrq)
581 struct nfsrv_descript *nfsd;
582 struct nfssvc_sock *slp;
583 struct proc *procp;
584 struct mbuf **mrq;
585 {
586 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
587 struct mbuf *nam = nfsd->nd_nam;
588 caddr_t dpos = nfsd->nd_dpos;
589 struct ucred *cred = &nfsd->nd_cr;
590 struct mbuf *m;
591 struct nfs_fattr *fp;
592 u_int32_t *tl;
593 int32_t t1;
594 int i;
595 caddr_t bpos;
596 int error = 0, rdonly, cache, getret;
597 int v3 = (nfsd->nd_flag & ND_NFSV3);
598 uint32_t reqlen, len, cnt, left, tlen;
599 char *cp2;
600 struct mbuf *mb, *mreq;
601 struct vnode *vp;
602 nfsfh_t nfh;
603 fhandle_t *fhp;
604 struct uio io, *uiop = &io;
605 struct vattr va;
606 off_t off;
607 u_quad_t frev;
608
609 fhp = &nfh.fh_generic;
610 nfsm_srvmtofh(fhp);
611 if (v3) {
612 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
613 off = fxdr_hyper(tl);
614 } else {
615 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
616 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
617 }
618 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
619 reqlen = fxdr_unsigned(uint32_t, *tl);
620 reqlen = MIN(reqlen, NFS_SRVMAXDATA(nfsd));
621 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
622 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
623 if (error) {
624 nfsm_reply(2 * NFSX_UNSIGNED);
625 nfsm_srvpostop_attr(1, (struct vattr *)0);
626 return (0);
627 }
628 if (vp->v_type != VREG) {
629 if (v3)
630 error = EINVAL;
631 else
632 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
633 }
634 if (!error) {
635 nqsrv_getl(vp, ND_READ);
636 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
637 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
638 }
639 getret = VOP_GETATTR(vp, &va, cred, procp);
640 if (!error)
641 error = getret;
642 if (error) {
643 vput(vp);
644 nfsm_reply(NFSX_POSTOPATTR(v3));
645 nfsm_srvpostop_attr(getret, &va);
646 return (0);
647 }
648 if (off >= va.va_size)
649 cnt = 0;
650 else if ((off + reqlen) > va.va_size)
651 cnt = nfsm_rndup(va.va_size - off);
652 else
653 cnt = reqlen;
654 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
655 if (v3) {
656 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
657 *tl++ = nfs_true;
658 fp = (struct nfs_fattr *)tl;
659 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
660 } else {
661 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
662 fp = (struct nfs_fattr *)tl;
663 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
664 }
665 len = left = cnt;
666 if (cnt > 0) {
667 if (nfsd_use_loan) {
668 struct vm_page **pgpp;
669 voff_t pgoff = trunc_page(off);
670 int orignpages, nleftpages;
671 vaddr_t lva, curlva;
672
673 orignpages = (round_page(off + cnt) - pgoff)
674 >> PAGE_SHIFT;
675 KASSERT(orignpages <= M_EXT_MAXPAGES); /* XXX */
676
677 lva = sokvaalloc(orignpages << PAGE_SHIFT, slp->ns_so);
678 if (lva == 0) {
679 /* fall back to VOP_READ */
680 goto loan_fail;
681 }
682
683 m = m_get(M_WAIT, MT_DATA);
684 pgpp = m->m_ext.ext_pgs;
685
686 curlva = lva;
687 nleftpages = orignpages;
688 while (nleftpages > 0) {
689 int npages = nleftpages;
690 if (npages > NFSD_READ_GETPAGES_CHUNK)
691 npages = NFSD_READ_GETPAGES_CHUNK;
692 again:
693 simple_lock(&vp->v_interlock);
694 error = VOP_GETPAGES(vp, pgoff, pgpp, &npages,
695 0, VM_PROT_READ, 0, PGO_SYNCIO);
696 if (error == EAGAIN) {
697 tsleep(&lbolt, PVM, "nfsread", 0);
698 goto again;
699 }
700 if (error) {
701 uvm_unloan(m->m_ext.ext_pgs,
702 orignpages - nleftpages,
703 UVM_LOAN_TOPAGE);
704 sokvafree(lva,
705 orignpages << PAGE_SHIFT);
706 m_free(m);
707 goto read_error;
708 }
709
710 /* loan and unbusy pages */
711 simple_lock(&vp->v_interlock);
712 for (i = 0; i < npages; i++) {
713 if (pgpp[i]->flags & PG_RELEASED) {
714 uvm_lock_pageq();
715 uvm_page_unbusy(pgpp, npages);
716 uvm_unlock_pageq();
717 simple_unlock(&vp->v_interlock);
718 continue;
719 }
720 }
721 uvm_loanuobjpages(pgpp, npages);
722 simple_unlock(&vp->v_interlock);
723
724 /* map pages */
725 for (i = 0; i < npages; i++) {
726 pmap_kenter_pa(curlva,
727 VM_PAGE_TO_PHYS(pgpp[i]),
728 VM_PROT_READ);
729 curlva += PAGE_SIZE;
730 }
731 nleftpages -= npages;
732 pgpp += npages;
733 pgoff += npages << PAGE_SHIFT;
734 }
735
736 lva += off & PAGE_MASK;
737
738 MCLAIM(m, &nfs_mowner);
739 MEXTADD(m, (void *)lva, cnt, M_MBUF, soloanfree,
740 slp->ns_so);
741 m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
742 m->m_len = cnt;
743
744 pmap_update(pmap_kernel());
745 mb->m_next = m;
746 mb = m;
747 error = 0;
748 uiop->uio_resid = 0;
749 } else {
750 struct iovec *iv;
751 struct iovec *iv2;
752 struct mbuf *m2;
753 int siz;
754 loan_fail:
755 /*
756 * Generate the mbuf list with the uio_iov ref. to it.
757 */
758 i = 0;
759 m = m2 = mb;
760 while (left > 0) {
761 siz = min(M_TRAILINGSPACE(m), left);
762 if (siz > 0) {
763 left -= siz;
764 i++;
765 }
766 if (left > 0) {
767 m = m_get(M_WAIT, MT_DATA);
768 MCLAIM(m, &nfs_mowner);
769 m_clget(m, M_WAIT);
770 m->m_len = 0;
771 m2->m_next = m;
772 m2 = m;
773 }
774 }
775 iv = malloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
776 uiop->uio_iov = iv2 = iv;
777 m = mb;
778 left = cnt;
779 i = 0;
780 while (left > 0) {
781 if (m == NULL)
782 panic("nfsrv_read iov");
783 siz = min(M_TRAILINGSPACE(m), left);
784 if (siz > 0) {
785 iv->iov_base = mtod(m, caddr_t) +
786 m->m_len;
787 iv->iov_len = siz;
788 m->m_len += siz;
789 left -= siz;
790 iv++;
791 i++;
792 }
793 m = m->m_next;
794 }
795 uiop->uio_iovcnt = i;
796 uiop->uio_offset = off;
797 uiop->uio_resid = cnt;
798 uiop->uio_rw = UIO_READ;
799 uiop->uio_segflg = UIO_SYSSPACE;
800 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
801 off = uiop->uio_offset;
802 free((caddr_t)iv2, M_TEMP);
803 }
804 read_error:
805 if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
806 if (!error)
807 error = getret;
808 m_freem(mreq);
809 vput(vp);
810 nfsm_reply(NFSX_POSTOPATTR(v3));
811 nfsm_srvpostop_attr(getret, &va);
812 return (0);
813 }
814 } else {
815 uiop->uio_resid = 0;
816 }
817 vput(vp);
818 nfsm_srvfillattr(&va, fp);
819 len -= uiop->uio_resid;
820 tlen = nfsm_rndup(len);
821 if (cnt != tlen || tlen != len)
822 nfsm_adj(mb, (int)cnt - tlen, tlen - len);
823 if (v3) {
824 *tl++ = txdr_unsigned(len);
825 if (len < reqlen)
826 *tl++ = nfs_true;
827 else
828 *tl++ = nfs_false;
829 }
830 *tl = txdr_unsigned(len);
831 nfsm_srvdone;
832 }
833
834 /*
835 * nfs write service
836 */
837 int
838 nfsrv_write(nfsd, slp, procp, mrq)
839 struct nfsrv_descript *nfsd;
840 struct nfssvc_sock *slp;
841 struct proc *procp;
842 struct mbuf **mrq;
843 {
844 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
845 struct mbuf *nam = nfsd->nd_nam;
846 caddr_t dpos = nfsd->nd_dpos;
847 struct ucred *cred = &nfsd->nd_cr;
848 struct iovec *ivp;
849 int i, cnt;
850 struct mbuf *mp;
851 struct nfs_fattr *fp;
852 struct iovec *iv;
853 struct vattr va, forat;
854 u_int32_t *tl;
855 int32_t t1;
856 caddr_t bpos;
857 int error = 0, rdonly, cache, len, forat_ret = 1;
858 int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
859 int stable = NFSV3WRITE_FILESYNC;
860 int v3 = (nfsd->nd_flag & ND_NFSV3);
861 char *cp2;
862 struct mbuf *mb, *mreq;
863 struct vnode *vp;
864 nfsfh_t nfh;
865 fhandle_t *fhp;
866 struct uio io, *uiop = &io;
867 off_t off;
868 u_quad_t frev;
869
870 if (mrep == NULL) {
871 *mrq = NULL;
872 return (0);
873 }
874 fhp = &nfh.fh_generic;
875 nfsm_srvmtofh(fhp);
876 if (v3) {
877 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
878 off = fxdr_hyper(tl);
879 tl += 3;
880 stable = fxdr_unsigned(int, *tl++);
881 } else {
882 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
883 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
884 tl += 2;
885 }
886 retlen = len = fxdr_unsigned(int32_t, *tl);
887 cnt = i = 0;
888
889 /*
890 * For NFS Version 2, it is not obvious what a write of zero length
891 * should do, but I might as well be consistent with Version 3,
892 * which is to return ok so long as there are no permission problems.
893 */
894 if (len > 0) {
895 zeroing = 1;
896 mp = mrep;
897 while (mp) {
898 if (mp == md) {
899 zeroing = 0;
900 adjust = dpos - mtod(mp, caddr_t);
901 mp->m_len -= adjust;
902 if (mp->m_len > 0 && adjust > 0)
903 NFSMADV(mp, adjust);
904 }
905 if (zeroing)
906 mp->m_len = 0;
907 else if (mp->m_len > 0) {
908 i += mp->m_len;
909 if (i > len) {
910 mp->m_len -= (i - len);
911 zeroing = 1;
912 }
913 if (mp->m_len > 0)
914 cnt++;
915 }
916 mp = mp->m_next;
917 }
918 }
919 if (len > NFS_MAXDATA || len < 0 || i < len) {
920 error = EIO;
921 nfsm_reply(2 * NFSX_UNSIGNED);
922 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
923 return (0);
924 }
925 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
926 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
927 if (error) {
928 nfsm_reply(2 * NFSX_UNSIGNED);
929 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
930 return (0);
931 }
932 if (v3)
933 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
934 if (vp->v_type != VREG) {
935 if (v3)
936 error = EINVAL;
937 else
938 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
939 }
940 if (!error) {
941 nqsrv_getl(vp, ND_WRITE);
942 error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
943 }
944 if (error) {
945 vput(vp);
946 nfsm_reply(NFSX_WCCDATA(v3));
947 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
948 return (0);
949 }
950
951 if (len > 0) {
952 ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, M_WAITOK);
953 uiop->uio_iov = iv = ivp;
954 uiop->uio_iovcnt = cnt;
955 mp = mrep;
956 while (mp) {
957 if (mp->m_len > 0) {
958 ivp->iov_base = mtod(mp, caddr_t);
959 ivp->iov_len = mp->m_len;
960 ivp++;
961 }
962 mp = mp->m_next;
963 }
964
965 /*
966 * XXX
967 * The IO_METASYNC flag indicates that all metadata (and not
968 * just enough to ensure data integrity) must be written to
969 * stable storage synchronously.
970 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
971 */
972 if (stable == NFSV3WRITE_UNSTABLE)
973 ioflags = IO_NODELOCKED;
974 else if (stable == NFSV3WRITE_DATASYNC)
975 ioflags = (IO_SYNC | IO_NODELOCKED);
976 else
977 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
978 uiop->uio_resid = len;
979 uiop->uio_rw = UIO_WRITE;
980 uiop->uio_segflg = UIO_SYSSPACE;
981 uiop->uio_procp = (struct proc *)0;
982 uiop->uio_offset = off;
983 error = VOP_WRITE(vp, uiop, ioflags, cred);
984 nfsstats.srvvop_writes++;
985 free(iv, M_TEMP);
986 }
987 aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
988 vput(vp);
989 if (!error)
990 error = aftat_ret;
991 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
992 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
993 if (v3) {
994 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
995 if (error)
996 return (0);
997 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
998 *tl++ = txdr_unsigned(retlen);
999 if (stable == NFSV3WRITE_UNSTABLE)
1000 *tl++ = txdr_unsigned(stable);
1001 else
1002 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1003 /*
1004 * Actually, there is no need to txdr these fields,
1005 * but it may make the values more human readable,
1006 * for debugging purposes.
1007 */
1008 *tl++ = txdr_unsigned(boottime.tv_sec);
1009 *tl = txdr_unsigned(boottime.tv_usec);
1010 } else {
1011 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1012 nfsm_srvfillattr(&va, fp);
1013 }
1014 nfsm_srvdone;
1015 }
1016
1017 /*
1018 * NFS write service with write gathering support. Called when
1019 * nfsrvw_procrastinate > 0.
1020 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1021 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1022 * Jan. 1994.
1023 */
1024 int
1025 nfsrv_writegather(ndp, slp, procp, mrq)
1026 struct nfsrv_descript **ndp;
1027 struct nfssvc_sock *slp;
1028 struct proc *procp;
1029 struct mbuf **mrq;
1030 {
1031 struct iovec *ivp;
1032 struct mbuf *mp;
1033 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1034 struct nfs_fattr *fp;
1035 int i = 0;
1036 struct iovec *iov;
1037 struct nfsrvw_delayhash *wpp;
1038 struct ucred *cred;
1039 struct vattr va, forat;
1040 u_int32_t *tl;
1041 int32_t t1;
1042 caddr_t bpos, dpos;
1043 int error = 0, rdonly, cache, len = 0, forat_ret = 1;
1044 int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
1045 char *cp2;
1046 struct mbuf *mb, *mreq, *mrep, *md;
1047 struct vnode *vp;
1048 struct uio io, *uiop = &io;
1049 u_quad_t frev, cur_usec;
1050
1051 *mrq = NULL;
1052 if (*ndp) {
1053 nfsd = *ndp;
1054 *ndp = NULL;
1055 mrep = nfsd->nd_mrep;
1056 md = nfsd->nd_md;
1057 dpos = nfsd->nd_dpos;
1058 cred = &nfsd->nd_cr;
1059 v3 = (nfsd->nd_flag & ND_NFSV3);
1060 LIST_INIT(&nfsd->nd_coalesce);
1061 nfsd->nd_mreq = NULL;
1062 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1063 cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
1064 nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
1065
1066 /*
1067 * Now, get the write header..
1068 */
1069 nfsm_srvmtofh(&nfsd->nd_fh);
1070 if (v3) {
1071 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1072 nfsd->nd_off = fxdr_hyper(tl);
1073 tl += 3;
1074 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1075 } else {
1076 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1077 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1078 tl += 2;
1079 }
1080 len = fxdr_unsigned(int32_t, *tl);
1081 nfsd->nd_len = len;
1082 nfsd->nd_eoff = nfsd->nd_off + len;
1083
1084 /*
1085 * Trim the header out of the mbuf list and trim off any trailing
1086 * junk so that the mbuf list has only the write data.
1087 */
1088 zeroing = 1;
1089 i = 0;
1090 mp = mrep;
1091 while (mp) {
1092 if (mp == md) {
1093 zeroing = 0;
1094 adjust = dpos - mtod(mp, caddr_t);
1095 mp->m_len -= adjust;
1096 if (mp->m_len > 0 && adjust > 0)
1097 NFSMADV(mp, adjust);
1098 }
1099 if (zeroing)
1100 mp->m_len = 0;
1101 else {
1102 i += mp->m_len;
1103 if (i > len) {
1104 mp->m_len -= (i - len);
1105 zeroing = 1;
1106 }
1107 }
1108 mp = mp->m_next;
1109 }
1110 if (len > NFS_MAXDATA || len < 0 || i < len) {
1111 nfsmout:
1112 m_freem(mrep);
1113 error = EIO;
1114 nfsm_writereply(2 * NFSX_UNSIGNED, v3);
1115 if (v3)
1116 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1117 nfsd->nd_mreq = mreq;
1118 nfsd->nd_mrep = NULL;
1119 nfsd->nd_time = 0;
1120 }
1121
1122 /*
1123 * Add this entry to the hash and time queues.
1124 */
1125 s = splsoftclock();
1126 owp = NULL;
1127 wp = LIST_FIRST(&slp->ns_tq);
1128 while (wp && wp->nd_time < nfsd->nd_time) {
1129 owp = wp;
1130 wp = LIST_NEXT(wp, nd_tq);
1131 }
1132 if (owp) {
1133 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1134 } else {
1135 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1136 }
1137 if (nfsd->nd_mrep) {
1138 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1139 owp = NULL;
1140 wp = LIST_FIRST(wpp);
1141 while (wp &&
1142 memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1143 owp = wp;
1144 wp = LIST_NEXT(wp, nd_hash);
1145 }
1146 while (wp && wp->nd_off < nfsd->nd_off &&
1147 !memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1148 owp = wp;
1149 wp = LIST_NEXT(wp, nd_hash);
1150 }
1151 if (owp) {
1152 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1153
1154 /*
1155 * Search the hash list for overlapping entries and
1156 * coalesce.
1157 */
1158 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1159 wp = LIST_NEXT(nfsd, nd_hash);
1160 if (NFSW_SAMECRED(owp, nfsd))
1161 nfsrvw_coalesce(owp, nfsd);
1162 }
1163 } else {
1164 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1165 }
1166 }
1167 splx(s);
1168 }
1169
1170 /*
1171 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1172 * and generate the associated reply mbuf list(s).
1173 */
1174 loop1:
1175 cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
1176 s = splsoftclock();
1177 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
1178 owp = LIST_NEXT(nfsd, nd_tq);
1179 if (nfsd->nd_time > cur_usec)
1180 break;
1181 if (nfsd->nd_mreq)
1182 continue;
1183 LIST_REMOVE(nfsd, nd_tq);
1184 LIST_REMOVE(nfsd, nd_hash);
1185 splx(s);
1186 mrep = nfsd->nd_mrep;
1187 nfsd->nd_mrep = NULL;
1188 cred = &nfsd->nd_cr;
1189 v3 = (nfsd->nd_flag & ND_NFSV3);
1190 forat_ret = aftat_ret = 1;
1191 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1192 nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH),
1193 FALSE);
1194 if (!error) {
1195 if (v3)
1196 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
1197 if (vp->v_type != VREG) {
1198 if (v3)
1199 error = EINVAL;
1200 else
1201 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1202 }
1203 } else
1204 vp = NULL;
1205 if (!error) {
1206 nqsrv_getl(vp, ND_WRITE);
1207 error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1208 }
1209
1210 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1211 ioflags = IO_NODELOCKED;
1212 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1213 ioflags = (IO_SYNC | IO_NODELOCKED);
1214 else
1215 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1216 uiop->uio_rw = UIO_WRITE;
1217 uiop->uio_segflg = UIO_SYSSPACE;
1218 uiop->uio_procp = (struct proc *)0;
1219 uiop->uio_offset = nfsd->nd_off;
1220 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1221 if (uiop->uio_resid > 0) {
1222 mp = mrep;
1223 i = 0;
1224 while (mp) {
1225 if (mp->m_len > 0)
1226 i++;
1227 mp = mp->m_next;
1228 }
1229 uiop->uio_iovcnt = i;
1230 iov = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
1231 uiop->uio_iov = ivp = iov;
1232 mp = mrep;
1233 while (mp) {
1234 if (mp->m_len > 0) {
1235 ivp->iov_base = mtod(mp, caddr_t);
1236 ivp->iov_len = mp->m_len;
1237 ivp++;
1238 }
1239 mp = mp->m_next;
1240 }
1241 if (!error) {
1242 error = VOP_WRITE(vp, uiop, ioflags, cred);
1243 nfsstats.srvvop_writes++;
1244 }
1245 free((caddr_t)iov, M_TEMP);
1246 }
1247 m_freem(mrep);
1248 if (vp) {
1249 aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
1250 vput(vp);
1251 }
1252
1253 /*
1254 * Loop around generating replies for all write rpcs that have
1255 * now been completed.
1256 */
1257 swp = nfsd;
1258 do {
1259 if (error) {
1260 nfsm_writereply(NFSX_WCCDATA(v3), v3);
1261 if (v3) {
1262 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1263 }
1264 } else {
1265 nfsm_writereply(NFSX_PREOPATTR(v3) +
1266 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1267 NFSX_WRITEVERF(v3), v3);
1268 if (v3) {
1269 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1270 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1271 *tl++ = txdr_unsigned(nfsd->nd_len);
1272 *tl++ = txdr_unsigned(swp->nd_stable);
1273 /*
1274 * Actually, there is no need to txdr these fields,
1275 * but it may make the values more human readable,
1276 * for debugging purposes.
1277 */
1278 *tl++ = txdr_unsigned(boottime.tv_sec);
1279 *tl = txdr_unsigned(boottime.tv_usec);
1280 } else {
1281 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1282 nfsm_srvfillattr(&va, fp);
1283 }
1284 }
1285 nfsd->nd_mreq = mreq;
1286 if (nfsd->nd_mrep)
1287 panic("nfsrv_write: nd_mrep not free");
1288
1289 /*
1290 * Done. Put it at the head of the timer queue so that
1291 * the final phase can return the reply.
1292 */
1293 s = splsoftclock();
1294 if (nfsd != swp) {
1295 nfsd->nd_time = 0;
1296 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1297 }
1298 nfsd = LIST_FIRST(&swp->nd_coalesce);
1299 if (nfsd) {
1300 LIST_REMOVE(nfsd, nd_tq);
1301 }
1302 splx(s);
1303 } while (nfsd);
1304 s = splsoftclock();
1305 swp->nd_time = 0;
1306 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1307 splx(s);
1308 goto loop1;
1309 }
1310 splx(s);
1311
1312 /*
1313 * Search for a reply to return.
1314 */
1315 s = splsoftclock();
1316 LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) {
1317 if (nfsd->nd_mreq) {
1318 LIST_REMOVE(nfsd, nd_tq);
1319 *mrq = nfsd->nd_mreq;
1320 *ndp = nfsd;
1321 break;
1322 }
1323 }
1324 splx(s);
1325 return (0);
1326 }
1327
1328 /*
1329 * Coalesce the write request nfsd into owp. To do this we must:
1330 * - remove nfsd from the queues
1331 * - merge nfsd->nd_mrep into owp->nd_mrep
1332 * - update the nd_eoff and nd_stable for owp
1333 * - put nfsd on owp's nd_coalesce list
1334 * NB: Must be called at splsoftclock().
1335 */
1336 void
1337 nfsrvw_coalesce(owp, nfsd)
1338 struct nfsrv_descript *owp;
1339 struct nfsrv_descript *nfsd;
1340 {
1341 int overlap;
1342 struct mbuf *mp;
1343 struct nfsrv_descript *m;
1344
1345 LIST_REMOVE(nfsd, nd_hash);
1346 LIST_REMOVE(nfsd, nd_tq);
1347 if (owp->nd_eoff < nfsd->nd_eoff) {
1348 overlap = owp->nd_eoff - nfsd->nd_off;
1349 if (overlap < 0)
1350 panic("nfsrv_coalesce: bad off");
1351 if (overlap > 0)
1352 m_adj(nfsd->nd_mrep, overlap);
1353 mp = owp->nd_mrep;
1354 while (mp->m_next)
1355 mp = mp->m_next;
1356 mp->m_next = nfsd->nd_mrep;
1357 owp->nd_eoff = nfsd->nd_eoff;
1358 } else
1359 m_freem(nfsd->nd_mrep);
1360 nfsd->nd_mrep = NULL;
1361 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1362 owp->nd_stable = NFSV3WRITE_FILESYNC;
1363 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1364 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1365 owp->nd_stable = NFSV3WRITE_DATASYNC;
1366 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1367 /*
1368 * nfsd might hold coalesce elements! Move them to owp.
1369 * Otherwise, requests may be lost and clients will be stuck.
1370 */
1371 while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) {
1372 LIST_REMOVE(m, nd_tq);
1373 LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
1374 }
1375 }
1376
1377 /*
1378 * nfs create service
1379 * now does a truncate to 0 length via. setattr if it already exists
1380 */
1381 int
1382 nfsrv_create(nfsd, slp, procp, mrq)
1383 struct nfsrv_descript *nfsd;
1384 struct nfssvc_sock *slp;
1385 struct proc *procp;
1386 struct mbuf **mrq;
1387 {
1388 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1389 struct mbuf *nam = nfsd->nd_nam;
1390 caddr_t dpos = nfsd->nd_dpos;
1391 struct ucred *cred = &nfsd->nd_cr;
1392 struct nfs_fattr *fp;
1393 struct vattr va, dirfor, diraft;
1394 struct nfsv2_sattr *sp;
1395 u_int32_t *tl;
1396 struct nameidata nd;
1397 caddr_t cp;
1398 int32_t t1;
1399 caddr_t bpos;
1400 int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1401 int rdev = 0;
1402 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1403 char *cp2;
1404 struct mbuf *mb, *mreq;
1405 struct vnode *vp = NULL, *dirp = NULL;
1406 nfsfh_t nfh;
1407 fhandle_t *fhp;
1408 u_quad_t frev, tempsize;
1409 u_char cverf[NFSX_V3CREATEVERF];
1410
1411 nd.ni_cnd.cn_nameiop = 0;
1412 fhp = &nfh.fh_generic;
1413 nfsm_srvmtofh(fhp);
1414 nfsm_srvnamesiz(len);
1415 nd.ni_cnd.cn_cred = cred;
1416 nd.ni_cnd.cn_nameiop = CREATE;
1417 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1418 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1419 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1420 if (dirp) {
1421 if (v3)
1422 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
1423 procp);
1424 else {
1425 vrele(dirp);
1426 dirp = (struct vnode *)0;
1427 }
1428 }
1429 if (error) {
1430 nfsm_reply(NFSX_WCCDATA(v3));
1431 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1432 if (dirp)
1433 vrele(dirp);
1434 return (0);
1435 }
1436 VATTR_NULL(&va);
1437 if (v3) {
1438 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1439 how = fxdr_unsigned(int, *tl);
1440 switch (how) {
1441 case NFSV3CREATE_GUARDED:
1442 if (nd.ni_vp) {
1443 error = EEXIST;
1444 break;
1445 }
1446 case NFSV3CREATE_UNCHECKED:
1447 nfsm_srvsattr(&va);
1448 break;
1449 case NFSV3CREATE_EXCLUSIVE:
1450 nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1451 memcpy(cverf, cp, NFSX_V3CREATEVERF);
1452 exclusive_flag = 1;
1453 if (nd.ni_vp == NULL)
1454 va.va_mode = 0;
1455 break;
1456 };
1457 va.va_type = VREG;
1458 } else {
1459 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1460 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1461 if (va.va_type == VNON)
1462 va.va_type = VREG;
1463 va.va_mode = nfstov_mode(sp->sa_mode);
1464 switch (va.va_type) {
1465 case VREG:
1466 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1467 if (tsize != -1)
1468 va.va_size = (u_quad_t)tsize;
1469 break;
1470 case VCHR:
1471 case VBLK:
1472 case VFIFO:
1473 rdev = fxdr_unsigned(int32_t, sp->sa_size);
1474 break;
1475 default:
1476 break;
1477 };
1478 }
1479
1480 /*
1481 * Iff doesn't exist, create it
1482 * otherwise just truncate to 0 length
1483 * should I set the mode too ??
1484 */
1485 if (nd.ni_vp == NULL) {
1486 if (va.va_type == VREG || va.va_type == VSOCK) {
1487 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1488 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1489 if (!error) {
1490 if (exclusive_flag) {
1491 exclusive_flag = 0;
1492 VATTR_NULL(&va);
1493 memcpy((caddr_t)&va.va_atime, cverf,
1494 NFSX_V3CREATEVERF);
1495 error = VOP_SETATTR(nd.ni_vp, &va, cred,
1496 procp);
1497 }
1498 }
1499 } else if (va.va_type == VCHR || va.va_type == VBLK ||
1500 va.va_type == VFIFO) {
1501 if (va.va_type == VCHR && rdev == 0xffffffff)
1502 va.va_type = VFIFO;
1503 if (va.va_type != VFIFO &&
1504 (error = suser(cred, (u_short *)0))) {
1505 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1506 vput(nd.ni_dvp);
1507 nfsm_reply(0);
1508 return (error);
1509 } else
1510 va.va_rdev = (dev_t)rdev;
1511 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1512 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
1513 &va);
1514 if (error) {
1515 nfsm_reply(0);
1516 }
1517 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1518 vrele(nd.ni_dvp);
1519 vput(nd.ni_vp);
1520 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1521 error = EINVAL;
1522 nfsm_reply(0);
1523 }
1524 } else {
1525 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1526 vput(nd.ni_dvp);
1527 error = ENXIO;
1528 }
1529 vp = nd.ni_vp;
1530 } else {
1531 vp = nd.ni_vp;
1532 if (nd.ni_dvp == vp)
1533 vrele(nd.ni_dvp);
1534 else
1535 vput(nd.ni_dvp);
1536 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1537 if (!error && va.va_size != -1) {
1538 error = nfsrv_access(vp, VWRITE, cred,
1539 (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
1540 if (!error) {
1541 nqsrv_getl(vp, ND_WRITE);
1542 tempsize = va.va_size;
1543 VATTR_NULL(&va);
1544 va.va_size = tempsize;
1545 error = VOP_SETATTR(vp, &va, cred,
1546 procp);
1547 }
1548 }
1549 if (error)
1550 vput(vp);
1551 }
1552 if (!error) {
1553 memset((caddr_t)fhp, 0, sizeof(nfh));
1554 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1555 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1556 if (!error)
1557 error = VOP_GETATTR(vp, &va, cred, procp);
1558 vput(vp);
1559 }
1560 if (v3) {
1561 if (exclusive_flag && !error &&
1562 memcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
1563 error = EEXIST;
1564 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1565 vrele(dirp);
1566 }
1567 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1568 if (v3) {
1569 if (!error) {
1570 nfsm_srvpostop_fh(fhp);
1571 nfsm_srvpostop_attr(0, &va);
1572 }
1573 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1574 } else {
1575 nfsm_srvfhtom(fhp, v3);
1576 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1577 nfsm_srvfillattr(&va, fp);
1578 }
1579 return (0);
1580 nfsmout:
1581 if (dirp)
1582 vrele(dirp);
1583 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1584 if (nd.ni_dvp == nd.ni_vp)
1585 vrele(nd.ni_dvp);
1586 else
1587 vput(nd.ni_dvp);
1588 if (nd.ni_vp)
1589 vput(nd.ni_vp);
1590 return (error);
1591 }
1592
1593 /*
1594 * nfs v3 mknod service
1595 */
1596 int
1597 nfsrv_mknod(nfsd, slp, procp, mrq)
1598 struct nfsrv_descript *nfsd;
1599 struct nfssvc_sock *slp;
1600 struct proc *procp;
1601 struct mbuf **mrq;
1602 {
1603 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1604 struct mbuf *nam = nfsd->nd_nam;
1605 caddr_t dpos = nfsd->nd_dpos;
1606 struct ucred *cred = &nfsd->nd_cr;
1607 struct vattr va, dirfor, diraft;
1608 u_int32_t *tl;
1609 struct nameidata nd;
1610 int32_t t1;
1611 caddr_t bpos;
1612 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
1613 u_int32_t major, minor;
1614 enum vtype vtyp;
1615 char *cp2;
1616 struct mbuf *mb, *mreq;
1617 struct vnode *vp, *dirp = (struct vnode *)0;
1618 nfsfh_t nfh;
1619 fhandle_t *fhp;
1620 u_quad_t frev;
1621
1622 nd.ni_cnd.cn_nameiop = 0;
1623 fhp = &nfh.fh_generic;
1624 nfsm_srvmtofh(fhp);
1625 nfsm_srvnamesiz(len);
1626 nd.ni_cnd.cn_cred = cred;
1627 nd.ni_cnd.cn_nameiop = CREATE;
1628 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1629 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1630 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1631 if (dirp)
1632 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
1633 if (error) {
1634 nfsm_reply(NFSX_WCCDATA(1));
1635 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1636 if (dirp)
1637 vrele(dirp);
1638 return (0);
1639 }
1640 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1641 vtyp = nfsv3tov_type(*tl);
1642 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1643 error = NFSERR_BADTYPE;
1644 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1645 if (nd.ni_dvp == nd.ni_vp)
1646 vrele(nd.ni_dvp);
1647 else
1648 vput(nd.ni_dvp);
1649 if (nd.ni_vp)
1650 vput(nd.ni_vp);
1651 goto out;
1652 }
1653 VATTR_NULL(&va);
1654 nfsm_srvsattr(&va);
1655 if (vtyp == VCHR || vtyp == VBLK) {
1656 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1657 major = fxdr_unsigned(u_int32_t, *tl++);
1658 minor = fxdr_unsigned(u_int32_t, *tl);
1659 va.va_rdev = makedev(major, minor);
1660 }
1661
1662 /*
1663 * Iff doesn't exist, create it.
1664 */
1665 if (nd.ni_vp) {
1666 error = EEXIST;
1667 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1668 if (nd.ni_dvp == nd.ni_vp)
1669 vrele(nd.ni_dvp);
1670 else
1671 vput(nd.ni_dvp);
1672 vput(nd.ni_vp);
1673 goto out;
1674 }
1675 va.va_type = vtyp;
1676 if (vtyp == VSOCK) {
1677 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1678 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1679 } else {
1680 if (va.va_type != VFIFO &&
1681 (error = suser(cred, (u_short *)0))) {
1682 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1683 vput(nd.ni_dvp);
1684 goto out;
1685 }
1686 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1687 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1688 if (error) {
1689 goto out;
1690 }
1691 if (error)
1692 goto out;
1693 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1694 vput(nd.ni_vp);
1695 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1696 error = EINVAL;
1697 }
1698 }
1699 out:
1700 vp = nd.ni_vp;
1701 if (!error) {
1702 memset((caddr_t)fhp, 0, sizeof(nfh));
1703 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1704 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1705 if (!error)
1706 error = VOP_GETATTR(vp, &va, cred, procp);
1707 vput(vp);
1708 }
1709 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1710 vrele(dirp);
1711 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1712 if (!error) {
1713 nfsm_srvpostop_fh(fhp);
1714 nfsm_srvpostop_attr(0, &va);
1715 }
1716 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1717 return (0);
1718 nfsmout:
1719 if (dirp)
1720 vrele(dirp);
1721 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1722 if (nd.ni_dvp == nd.ni_vp)
1723 vrele(nd.ni_dvp);
1724 else
1725 vput(nd.ni_dvp);
1726 if (nd.ni_vp)
1727 vput(nd.ni_vp);
1728 return (error);
1729 }
1730
1731 /*
1732 * nfs remove service
1733 */
1734 int
1735 nfsrv_remove(nfsd, slp, procp, mrq)
1736 struct nfsrv_descript *nfsd;
1737 struct nfssvc_sock *slp;
1738 struct proc *procp;
1739 struct mbuf **mrq;
1740 {
1741 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1742 struct mbuf *nam = nfsd->nd_nam;
1743 caddr_t dpos = nfsd->nd_dpos;
1744 struct ucred *cred = &nfsd->nd_cr;
1745 struct nameidata nd;
1746 u_int32_t *tl;
1747 int32_t t1;
1748 caddr_t bpos;
1749 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
1750 int v3 = (nfsd->nd_flag & ND_NFSV3);
1751 char *cp2;
1752 struct mbuf *mb, *mreq;
1753 struct vnode *vp, *dirp;
1754 struct vattr dirfor, diraft;
1755 nfsfh_t nfh;
1756 fhandle_t *fhp;
1757 u_quad_t frev;
1758
1759 #ifndef nolint
1760 vp = (struct vnode *)0;
1761 #endif
1762 fhp = &nfh.fh_generic;
1763 nfsm_srvmtofh(fhp);
1764 nfsm_srvnamesiz(len);
1765 nd.ni_cnd.cn_cred = cred;
1766 nd.ni_cnd.cn_nameiop = DELETE;
1767 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1768 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1769 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1770 if (dirp) {
1771 if (v3)
1772 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
1773 procp);
1774 else
1775 vrele(dirp);
1776 }
1777 if (!error) {
1778 vp = nd.ni_vp;
1779 if (vp->v_type == VDIR &&
1780 (error = suser(cred, (u_short *)0)) != 0)
1781 goto out;
1782 /*
1783 * The root of a mounted filesystem cannot be deleted.
1784 */
1785 if (vp->v_flag & VROOT) {
1786 error = EBUSY;
1787 goto out;
1788 }
1789 out:
1790 if (!error) {
1791 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1792 nqsrv_getl(vp, ND_WRITE);
1793 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1794 } else {
1795 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1796 if (nd.ni_dvp == vp)
1797 vrele(nd.ni_dvp);
1798 else
1799 vput(nd.ni_dvp);
1800 vput(vp);
1801 }
1802 }
1803 if (dirp && v3) {
1804 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1805 vrele(dirp);
1806 }
1807 nfsm_reply(NFSX_WCCDATA(v3));
1808 if (v3) {
1809 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1810 return (0);
1811 }
1812 nfsm_srvdone;
1813 }
1814
1815 /*
1816 * nfs rename service
1817 */
1818 int
1819 nfsrv_rename(nfsd, slp, procp, mrq)
1820 struct nfsrv_descript *nfsd;
1821 struct nfssvc_sock *slp;
1822 struct proc *procp;
1823 struct mbuf **mrq;
1824 {
1825 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1826 struct mbuf *nam = nfsd->nd_nam;
1827 caddr_t dpos = nfsd->nd_dpos;
1828 struct ucred *cred = &nfsd->nd_cr;
1829 u_int32_t *tl;
1830 int32_t t1;
1831 caddr_t bpos;
1832 int error = 0, cache, fdirfor_ret = 1, fdiraft_ret = 1;
1833 uint32_t len, len2;
1834 int tdirfor_ret = 1, tdiraft_ret = 1;
1835 int v3 = (nfsd->nd_flag & ND_NFSV3);
1836 char *cp2;
1837 struct mbuf *mb, *mreq;
1838 struct nameidata fromnd, tond;
1839 struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
1840 struct vnode *tdirp = (struct vnode *)0;
1841 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1842 nfsfh_t fnfh, tnfh;
1843 fhandle_t *ffhp, *tfhp;
1844 u_quad_t frev;
1845 uid_t saved_uid;
1846
1847 #ifndef nolint
1848 fvp = (struct vnode *)0;
1849 #endif
1850 ffhp = &fnfh.fh_generic;
1851 tfhp = &tnfh.fh_generic;
1852 fromnd.ni_cnd.cn_nameiop = 0;
1853 tond.ni_cnd.cn_nameiop = 0;
1854 nfsm_srvmtofh(ffhp);
1855 nfsm_srvnamesiz(len);
1856 /*
1857 * Remember our original uid so that we can reset cr_uid before
1858 * the second nfs_namei() call, in case it is remapped.
1859 */
1860 saved_uid = cred->cr_uid;
1861 fromnd.ni_cnd.cn_cred = cred;
1862 fromnd.ni_cnd.cn_nameiop = DELETE;
1863 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1864 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
1865 &dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1866 if (fdirp) {
1867 if (v3)
1868 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
1869 procp);
1870 else {
1871 vrele(fdirp);
1872 fdirp = (struct vnode *)0;
1873 }
1874 }
1875 if (error) {
1876 nfsm_reply(2 * NFSX_WCCDATA(v3));
1877 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1878 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1879 if (fdirp)
1880 vrele(fdirp);
1881 return (0);
1882 }
1883 fvp = fromnd.ni_vp;
1884 nfsm_srvmtofh(tfhp);
1885 if (v3) {
1886 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
1887 len2 = fxdr_unsigned(uint32_t, *tl);
1888 /* len2 will be checked by nfs_namei */
1889 }
1890 else {
1891 /* NFSv2 */
1892 nfsm_strsiz(len2, NFS_MAXNAMLEN);
1893 }
1894 cred->cr_uid = saved_uid;
1895 tond.ni_cnd.cn_cred = cred;
1896 tond.ni_cnd.cn_nameiop = RENAME;
1897 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1898 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
1899 &dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1900 if (tdirp) {
1901 if (v3)
1902 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
1903 procp);
1904 else {
1905 vrele(tdirp);
1906 tdirp = (struct vnode *)0;
1907 }
1908 }
1909 if (error) {
1910 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1911 vrele(fromnd.ni_dvp);
1912 vrele(fvp);
1913 goto out1;
1914 }
1915 tdvp = tond.ni_dvp;
1916 tvp = tond.ni_vp;
1917 if (tvp != NULL) {
1918 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1919 if (v3)
1920 error = EEXIST;
1921 else
1922 error = EISDIR;
1923 goto out;
1924 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1925 if (v3)
1926 error = EEXIST;
1927 else
1928 error = ENOTDIR;
1929 goto out;
1930 }
1931 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1932 if (v3)
1933 error = EXDEV;
1934 else
1935 error = ENOTEMPTY;
1936 goto out;
1937 }
1938 }
1939 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1940 if (v3)
1941 error = EXDEV;
1942 else
1943 error = ENOTEMPTY;
1944 goto out;
1945 }
1946 if (fvp->v_mount != tdvp->v_mount) {
1947 if (v3)
1948 error = EXDEV;
1949 else
1950 error = ENOTEMPTY;
1951 goto out;
1952 }
1953 if (fvp == tdvp) {
1954 if (v3)
1955 error = EINVAL;
1956 else
1957 error = ENOTEMPTY;
1958 }
1959 /*
1960 * If source is the same as the destination (that is the
1961 * same vnode with the same name in the same directory),
1962 * then there is nothing to do.
1963 */
1964 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1965 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1966 !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1967 fromnd.ni_cnd.cn_namelen))
1968 error = -1;
1969 out:
1970 if (!error) {
1971 nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
1972 nqsrv_getl(tdvp, ND_WRITE);
1973 if (tvp) {
1974 nqsrv_getl(tvp, ND_WRITE);
1975 }
1976 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1977 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1978 } else {
1979 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1980 if (tdvp == tvp)
1981 vrele(tdvp);
1982 else
1983 vput(tdvp);
1984 if (tvp)
1985 vput(tvp);
1986 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1987 vrele(fromnd.ni_dvp);
1988 vrele(fvp);
1989 if (error == -1)
1990 error = 0;
1991 }
1992 vrele(tond.ni_startdir);
1993 PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
1994 out1:
1995 if (fdirp) {
1996 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
1997 vrele(fdirp);
1998 }
1999 if (tdirp) {
2000 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
2001 vrele(tdirp);
2002 }
2003 vrele(fromnd.ni_startdir);
2004 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
2005 nfsm_reply(2 * NFSX_WCCDATA(v3));
2006 if (v3) {
2007 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2008 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2009 }
2010 return (0);
2011
2012 nfsmout:
2013 if (fdirp)
2014 vrele(fdirp);
2015 if (tdirp)
2016 vrele(tdirp);
2017 if (tond.ni_cnd.cn_nameiop) {
2018 vrele(tond.ni_startdir);
2019 PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
2020 }
2021 if (fromnd.ni_cnd.cn_nameiop) {
2022 vrele(fromnd.ni_startdir);
2023 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
2024 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2025 vrele(fromnd.ni_dvp);
2026 vrele(fvp);
2027 }
2028 return (error);
2029 }
2030
2031 /*
2032 * nfs link service
2033 */
2034 int
2035 nfsrv_link(nfsd, slp, procp, mrq)
2036 struct nfsrv_descript *nfsd;
2037 struct nfssvc_sock *slp;
2038 struct proc *procp;
2039 struct mbuf **mrq;
2040 {
2041 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2042 struct mbuf *nam = nfsd->nd_nam;
2043 caddr_t dpos = nfsd->nd_dpos;
2044 struct ucred *cred = &nfsd->nd_cr;
2045 struct nameidata nd;
2046 u_int32_t *tl;
2047 int32_t t1;
2048 caddr_t bpos;
2049 int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
2050 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2051 char *cp2;
2052 struct mbuf *mb, *mreq;
2053 struct vnode *vp, *xp, *dirp = (struct vnode *)0;
2054 struct vattr dirfor, diraft, at;
2055 nfsfh_t nfh, dnfh;
2056 fhandle_t *fhp, *dfhp;
2057 u_quad_t frev;
2058
2059 fhp = &nfh.fh_generic;
2060 dfhp = &dnfh.fh_generic;
2061 nfsm_srvmtofh(fhp);
2062 nfsm_srvmtofh(dfhp);
2063 nfsm_srvnamesiz(len);
2064 error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
2065 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2066 if (error) {
2067 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2068 nfsm_srvpostop_attr(getret, &at);
2069 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2070 return (0);
2071 }
2072 if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0)
2073 goto out1;
2074 nd.ni_cnd.cn_cred = cred;
2075 nd.ni_cnd.cn_nameiop = CREATE;
2076 nd.ni_cnd.cn_flags = LOCKPARENT;
2077 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2078 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2079 if (dirp) {
2080 if (v3)
2081 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2082 procp);
2083 else {
2084 vrele(dirp);
2085 dirp = (struct vnode *)0;
2086 }
2087 }
2088 if (error)
2089 goto out1;
2090 xp = nd.ni_vp;
2091 if (xp != NULL) {
2092 error = EEXIST;
2093 goto out;
2094 }
2095 xp = nd.ni_dvp;
2096 if (vp->v_mount != xp->v_mount)
2097 error = EXDEV;
2098 out:
2099 if (!error) {
2100 nqsrv_getl(vp, ND_WRITE);
2101 nqsrv_getl(xp, ND_WRITE);
2102 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2103 } else {
2104 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2105 if (nd.ni_dvp == nd.ni_vp)
2106 vrele(nd.ni_dvp);
2107 else
2108 vput(nd.ni_dvp);
2109 if (nd.ni_vp)
2110 vrele(nd.ni_vp);
2111 }
2112 out1:
2113 if (v3)
2114 getret = VOP_GETATTR(vp, &at, cred, procp);
2115 if (dirp) {
2116 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2117 vrele(dirp);
2118 }
2119 vrele(vp);
2120 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2121 if (v3) {
2122 nfsm_srvpostop_attr(getret, &at);
2123 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2124 return (0);
2125 }
2126 nfsm_srvdone;
2127 }
2128
2129 /*
2130 * nfs symbolic link service
2131 */
2132 int
2133 nfsrv_symlink(nfsd, slp, procp, mrq)
2134 struct nfsrv_descript *nfsd;
2135 struct nfssvc_sock *slp;
2136 struct proc *procp;
2137 struct mbuf **mrq;
2138 {
2139 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2140 struct mbuf *nam = nfsd->nd_nam;
2141 caddr_t dpos = nfsd->nd_dpos;
2142 struct ucred *cred = &nfsd->nd_cr;
2143 struct vattr va, dirfor, diraft;
2144 struct nameidata nd;
2145 u_int32_t *tl;
2146 int32_t t1;
2147 struct nfsv2_sattr *sp;
2148 char *bpos, *pathcp = NULL, *cp2;
2149 struct uio io;
2150 struct iovec iv;
2151 int error = 0, cache, dirfor_ret = 1, diraft_ret = 1;
2152 uint32_t len, len2;
2153 int v3 = (nfsd->nd_flag & ND_NFSV3);
2154 struct mbuf *mb, *mreq;
2155 struct vnode *dirp = (struct vnode *)0;
2156 nfsfh_t nfh;
2157 fhandle_t *fhp;
2158 u_quad_t frev;
2159
2160 nd.ni_cnd.cn_nameiop = 0;
2161 fhp = &nfh.fh_generic;
2162 nfsm_srvmtofh(fhp);
2163 nfsm_srvnamesiz(len);
2164 nd.ni_cnd.cn_cred = cred;
2165 nd.ni_cnd.cn_nameiop = CREATE;
2166 nd.ni_cnd.cn_flags = LOCKPARENT;
2167 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2168 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2169 if (dirp) {
2170 if (v3)
2171 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2172 procp);
2173 else {
2174 vrele(dirp);
2175 dirp = (struct vnode *)0;
2176 }
2177 }
2178 if (error)
2179 goto out;
2180 VATTR_NULL(&va);
2181 if (v3) {
2182 nfsm_srvsattr(&va);
2183 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
2184 len2 = fxdr_unsigned(uint32_t, *tl);
2185 if (len2 > PATH_MAX) {
2186 /* XXX should check _PC_NO_TRUNC */
2187 error = ENAMETOOLONG;
2188 goto abortop;
2189 }
2190 }
2191 else {
2192 /* NFSv2 */
2193 nfsm_strsiz(len2, NFS_MAXPATHLEN);
2194 }
2195 pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
2196 iv.iov_base = pathcp;
2197 iv.iov_len = len2;
2198 io.uio_resid = len2;
2199 io.uio_offset = 0;
2200 io.uio_iov = &iv;
2201 io.uio_iovcnt = 1;
2202 io.uio_segflg = UIO_SYSSPACE;
2203 io.uio_rw = UIO_READ;
2204 io.uio_procp = (struct proc *)0;
2205 nfsm_mtouio(&io, len2);
2206 if (!v3) {
2207 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2208 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
2209 }
2210 *(pathcp + len2) = '\0';
2211 if (nd.ni_vp) {
2212 error = EEXIST;
2213 abortop:
2214 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2215 if (nd.ni_dvp == nd.ni_vp)
2216 vrele(nd.ni_dvp);
2217 else
2218 vput(nd.ni_dvp);
2219 if (nd.ni_vp)
2220 vrele(nd.ni_vp);
2221 goto out;
2222 }
2223 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2224 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
2225 if (!error) {
2226 if (v3) {
2227 memset((caddr_t)fhp, 0, sizeof(nfh));
2228 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2229 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2230 if (!error)
2231 error = VOP_GETATTR(nd.ni_vp, &va, cred,
2232 procp);
2233 vput(nd.ni_vp);
2234 } else {
2235 vput(nd.ni_vp);
2236 }
2237 }
2238 out:
2239 if (pathcp)
2240 free(pathcp, M_TEMP);
2241 if (dirp) {
2242 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2243 vrele(dirp);
2244 }
2245 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2246 if (v3) {
2247 if (!error) {
2248 nfsm_srvpostop_fh(fhp);
2249 nfsm_srvpostop_attr(0, &va);
2250 }
2251 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2252 }
2253 return (0);
2254 nfsmout:
2255 if (dirp)
2256 vrele(dirp);
2257 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2258 if (nd.ni_dvp == nd.ni_vp)
2259 vrele(nd.ni_dvp);
2260 else
2261 vput(nd.ni_dvp);
2262 if (nd.ni_vp)
2263 vrele(nd.ni_vp);
2264 if (pathcp)
2265 free(pathcp, M_TEMP);
2266 return (error);
2267 }
2268
2269 /*
2270 * nfs mkdir service
2271 */
2272 int
2273 nfsrv_mkdir(nfsd, slp, procp, mrq)
2274 struct nfsrv_descript *nfsd;
2275 struct nfssvc_sock *slp;
2276 struct proc *procp;
2277 struct mbuf **mrq;
2278 {
2279 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2280 struct mbuf *nam = nfsd->nd_nam;
2281 caddr_t dpos = nfsd->nd_dpos;
2282 struct ucred *cred = &nfsd->nd_cr;
2283 struct vattr va, dirfor, diraft;
2284 struct nfs_fattr *fp;
2285 struct nameidata nd;
2286 caddr_t cp;
2287 u_int32_t *tl;
2288 int32_t t1;
2289 caddr_t bpos;
2290 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2291 int v3 = (nfsd->nd_flag & ND_NFSV3);
2292 char *cp2;
2293 struct mbuf *mb, *mreq;
2294 struct vnode *vp, *dirp = (struct vnode *)0;
2295 nfsfh_t nfh;
2296 fhandle_t *fhp;
2297 u_quad_t frev;
2298
2299 fhp = &nfh.fh_generic;
2300 nfsm_srvmtofh(fhp);
2301 nfsm_srvnamesiz(len);
2302 nd.ni_cnd.cn_cred = cred;
2303 nd.ni_cnd.cn_nameiop = CREATE;
2304 nd.ni_cnd.cn_flags = LOCKPARENT;
2305 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2306 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2307 if (dirp) {
2308 if (v3)
2309 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2310 procp);
2311 else {
2312 vrele(dirp);
2313 dirp = (struct vnode *)0;
2314 }
2315 }
2316 if (error) {
2317 nfsm_reply(NFSX_WCCDATA(v3));
2318 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2319 if (dirp)
2320 vrele(dirp);
2321 return (0);
2322 }
2323 VATTR_NULL(&va);
2324 if (v3) {
2325 nfsm_srvsattr(&va);
2326 } else {
2327 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2328 va.va_mode = nfstov_mode(*tl++);
2329 }
2330 va.va_type = VDIR;
2331 vp = nd.ni_vp;
2332 if (vp != NULL) {
2333 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2334 if (nd.ni_dvp == vp)
2335 vrele(nd.ni_dvp);
2336 else
2337 vput(nd.ni_dvp);
2338 vrele(vp);
2339 error = EEXIST;
2340 goto out;
2341 }
2342 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2343 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
2344 if (!error) {
2345 vp = nd.ni_vp;
2346 memset((caddr_t)fhp, 0, sizeof(nfh));
2347 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2348 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2349 if (!error)
2350 error = VOP_GETATTR(vp, &va, cred, procp);
2351 vput(vp);
2352 }
2353 out:
2354 if (dirp) {
2355 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2356 vrele(dirp);
2357 }
2358 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2359 if (v3) {
2360 if (!error) {
2361 nfsm_srvpostop_fh(fhp);
2362 nfsm_srvpostop_attr(0, &va);
2363 }
2364 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2365 } else {
2366 nfsm_srvfhtom(fhp, v3);
2367 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
2368 nfsm_srvfillattr(&va, fp);
2369 }
2370 return (0);
2371 nfsmout:
2372 if (dirp)
2373 vrele(dirp);
2374 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2375 if (nd.ni_dvp == nd.ni_vp)
2376 vrele(nd.ni_dvp);
2377 else
2378 vput(nd.ni_dvp);
2379 if (nd.ni_vp)
2380 vrele(nd.ni_vp);
2381 return (error);
2382 }
2383
2384 /*
2385 * nfs rmdir service
2386 */
2387 int
2388 nfsrv_rmdir(nfsd, slp, procp, mrq)
2389 struct nfsrv_descript *nfsd;
2390 struct nfssvc_sock *slp;
2391 struct proc *procp;
2392 struct mbuf **mrq;
2393 {
2394 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2395 struct mbuf *nam = nfsd->nd_nam;
2396 caddr_t dpos = nfsd->nd_dpos;
2397 struct ucred *cred = &nfsd->nd_cr;
2398 u_int32_t *tl;
2399 int32_t t1;
2400 caddr_t bpos;
2401 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2402 int v3 = (nfsd->nd_flag & ND_NFSV3);
2403 char *cp2;
2404 struct mbuf *mb, *mreq;
2405 struct vnode *vp, *dirp = (struct vnode *)0;
2406 struct vattr dirfor, diraft;
2407 nfsfh_t nfh;
2408 fhandle_t *fhp;
2409 struct nameidata nd;
2410 u_quad_t frev;
2411
2412 fhp = &nfh.fh_generic;
2413 nfsm_srvmtofh(fhp);
2414 nfsm_srvnamesiz(len);
2415 nd.ni_cnd.cn_cred = cred;
2416 nd.ni_cnd.cn_nameiop = DELETE;
2417 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2418 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2419 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2420 if (dirp) {
2421 if (v3)
2422 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2423 procp);
2424 else {
2425 vrele(dirp);
2426 dirp = (struct vnode *)0;
2427 }
2428 }
2429 if (error) {
2430 nfsm_reply(NFSX_WCCDATA(v3));
2431 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2432 if (dirp)
2433 vrele(dirp);
2434 return (0);
2435 }
2436 vp = nd.ni_vp;
2437 if (vp->v_type != VDIR) {
2438 error = ENOTDIR;
2439 goto out;
2440 }
2441 /*
2442 * No rmdir "." please.
2443 */
2444 if (nd.ni_dvp == vp) {
2445 error = EINVAL;
2446 goto out;
2447 }
2448 /*
2449 * The root of a mounted filesystem cannot be deleted.
2450 */
2451 if (vp->v_flag & VROOT)
2452 error = EBUSY;
2453 out:
2454 if (!error) {
2455 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2456 nqsrv_getl(vp, ND_WRITE);
2457 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2458 } else {
2459 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2460 if (nd.ni_dvp == nd.ni_vp)
2461 vrele(nd.ni_dvp);
2462 else
2463 vput(nd.ni_dvp);
2464 vput(vp);
2465 }
2466 if (dirp) {
2467 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2468 vrele(dirp);
2469 }
2470 nfsm_reply(NFSX_WCCDATA(v3));
2471 if (v3) {
2472 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2473 return (0);
2474 }
2475 nfsm_srvdone;
2476 }
2477
2478 /*
2479 * nfs readdir service
2480 * - mallocs what it thinks is enough to read
2481 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2482 * - calls VOP_READDIR()
2483 * - loops around building the reply
2484 * if the output generated exceeds count break out of loop
2485 * The nfsm_clget macro is used here so that the reply will be packed
2486 * tightly in mbuf clusters.
2487 * - it only knows that it has encountered eof when the VOP_READDIR()
2488 * reads nothing
2489 * - as such one readdir rpc will return eof false although you are there
2490 * and then the next will return eof
2491 * - it trims out records with d_fileno == 0
2492 * this doesn't matter for Unix clients, but they might confuse clients
2493 * for other os'.
2494 * - it trims out records with d_type == DT_WHT
2495 * these cannot be seen through NFS (unless we extend the protocol)
2496 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2497 * than requested, but this may not apply to all filesystems. For
2498 * example, client NFS does not { although it is never remote mounted
2499 * anyhow }
2500 * The alternate call nfsrv_readdirplus() does lookups as well.
2501 * PS: The NFS protocol spec. does not clarify what the "count" byte
2502 * argument is a count of.. just name strings and file id's or the
2503 * entire reply rpc or ...
2504 * I tried just file name and id sizes and it confused the Sun client,
2505 * so I am using the full rpc size now. The "paranoia.." comment refers
2506 * to including the status longwords that are not a part of the dir.
2507 * "entry" structures, but are in the rpc.
2508 */
2509 struct flrep {
2510 nfsuint64 fl_off;
2511 u_int32_t fl_postopok;
2512 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2513 u_int32_t fl_fhok;
2514 u_int32_t fl_fhsize;
2515 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2516 };
2517
2518 int
2519 nfsrv_readdir(nfsd, slp, procp, mrq)
2520 struct nfsrv_descript *nfsd;
2521 struct nfssvc_sock *slp;
2522 struct proc *procp;
2523 struct mbuf **mrq;
2524 {
2525 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2526 struct mbuf *nam = nfsd->nd_nam;
2527 caddr_t dpos = nfsd->nd_dpos;
2528 struct ucred *cred = &nfsd->nd_cr;
2529 char *bp, *be;
2530 struct mbuf *mp;
2531 struct dirent *dp;
2532 caddr_t cp;
2533 u_int32_t *tl;
2534 int32_t t1;
2535 caddr_t bpos;
2536 struct mbuf *mb, *mreq, *mp2;
2537 char *cpos, *cend, *cp2, *rbuf;
2538 struct vnode *vp;
2539 struct vattr at;
2540 nfsfh_t nfh;
2541 fhandle_t *fhp;
2542 struct uio io;
2543 struct iovec iv;
2544 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2545 int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
2546 int v3 = (nfsd->nd_flag & ND_NFSV3);
2547 u_quad_t frev, off, toff, verf;
2548 off_t *cookies = NULL, *cookiep;
2549 nfsuint64 jar;
2550
2551 fhp = &nfh.fh_generic;
2552 nfsm_srvmtofh(fhp);
2553 if (v3) {
2554 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2555 toff = fxdr_hyper(tl);
2556 tl += 2;
2557 verf = fxdr_hyper(tl);
2558 tl += 2;
2559 } else {
2560 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2561 toff = fxdr_unsigned(u_quad_t, *tl++);
2562 }
2563 off = toff;
2564 cnt = fxdr_unsigned(int, *tl);
2565 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2566 xfer = NFS_SRVMAXDATA(nfsd);
2567 if (siz > xfer)
2568 siz = xfer;
2569 fullsiz = siz;
2570 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2571 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2572 if (!error && vp->v_type != VDIR) {
2573 error = ENOTDIR;
2574 vput(vp);
2575 }
2576 if (error) {
2577 nfsm_reply(NFSX_UNSIGNED);
2578 nfsm_srvpostop_attr(getret, &at);
2579 return (0);
2580 }
2581 nqsrv_getl(vp, ND_READ);
2582 if (v3) {
2583 error = getret = VOP_GETATTR(vp, &at, cred, procp);
2584 #ifdef NFS3_STRICTVERF
2585 /*
2586 * XXX This check is too strict for Solaris 2.5 clients.
2587 */
2588 if (!error && toff && verf != at.va_filerev)
2589 error = NFSERR_BAD_COOKIE;
2590 #endif
2591 }
2592 if (!error)
2593 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
2594 if (error) {
2595 vput(vp);
2596 nfsm_reply(NFSX_POSTOPATTR(v3));
2597 nfsm_srvpostop_attr(getret, &at);
2598 return (0);
2599 }
2600 VOP_UNLOCK(vp, 0);
2601 rbuf = malloc(siz, M_TEMP, M_WAITOK);
2602 again:
2603 iv.iov_base = rbuf;
2604 iv.iov_len = fullsiz;
2605 io.uio_iov = &iv;
2606 io.uio_iovcnt = 1;
2607 io.uio_offset = (off_t)off;
2608 io.uio_resid = fullsiz;
2609 io.uio_segflg = UIO_SYSSPACE;
2610 io.uio_rw = UIO_READ;
2611 io.uio_procp = (struct proc *)0;
2612 eofflag = 0;
2613 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2614
2615 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
2616
2617 off = (off_t)io.uio_offset;
2618 if (!cookies && !error)
2619 error = NFSERR_PERM;
2620 if (v3) {
2621 getret = VOP_GETATTR(vp, &at, cred, procp);
2622 if (!error)
2623 error = getret;
2624 }
2625
2626 VOP_UNLOCK(vp, 0);
2627 if (error) {
2628 vrele(vp);
2629 free((caddr_t)rbuf, M_TEMP);
2630 if (cookies)
2631 free((caddr_t)cookies, M_TEMP);
2632 nfsm_reply(NFSX_POSTOPATTR(v3));
2633 nfsm_srvpostop_attr(getret, &at);
2634 return (0);
2635 }
2636 if (io.uio_resid) {
2637 siz -= io.uio_resid;
2638
2639 /*
2640 * If nothing read, return eof
2641 * rpc reply
2642 */
2643 if (siz == 0) {
2644 vrele(vp);
2645 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2646 2 * NFSX_UNSIGNED);
2647 if (v3) {
2648 nfsm_srvpostop_attr(getret, &at);
2649 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2650 txdr_hyper(at.va_filerev, tl);
2651 tl += 2;
2652 } else
2653 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2654 *tl++ = nfs_false;
2655 *tl = nfs_true;
2656 free((caddr_t)rbuf, M_TEMP);
2657 free((caddr_t)cookies, M_TEMP);
2658 return (0);
2659 }
2660 }
2661
2662 /*
2663 * Check for degenerate cases of nothing useful read.
2664 * If so go try again
2665 */
2666 cpos = rbuf;
2667 cend = rbuf + siz;
2668 dp = (struct dirent *)cpos;
2669 cookiep = cookies;
2670
2671 while (cpos < cend && ncookies > 0 &&
2672 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
2673 cpos += dp->d_reclen;
2674 dp = (struct dirent *)cpos;
2675 cookiep++;
2676 ncookies--;
2677 }
2678 if (cpos >= cend || ncookies == 0) {
2679 toff = off;
2680 siz = fullsiz;
2681 goto again;
2682 }
2683
2684 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
2685 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2686 if (v3) {
2687 nfsm_srvpostop_attr(getret, &at);
2688 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2689 txdr_hyper(at.va_filerev, tl);
2690 }
2691 mp = mp2 = mb;
2692 bp = bpos;
2693 be = bp + M_TRAILINGSPACE(mp);
2694
2695 /* Loop through the records and build reply */
2696 while (cpos < cend && ncookies > 0) {
2697 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2698 nlen = dp->d_namlen;
2699 rem = nfsm_rndup(nlen)-nlen;
2700 len += (4 * NFSX_UNSIGNED + nlen + rem);
2701 if (v3)
2702 len += 2 * NFSX_UNSIGNED;
2703 if (len > cnt) {
2704 eofflag = 0;
2705 break;
2706 }
2707 /*
2708 * Build the directory record xdr from
2709 * the dirent entry.
2710 */
2711 nfsm_clget;
2712 *tl = nfs_true;
2713 bp += NFSX_UNSIGNED;
2714 if (v3) {
2715 nfsm_clget;
2716 *tl = 0;
2717 bp += NFSX_UNSIGNED;
2718 }
2719 nfsm_clget;
2720 *tl = txdr_unsigned(dp->d_fileno);
2721 bp += NFSX_UNSIGNED;
2722 nfsm_clget;
2723 *tl = txdr_unsigned(nlen);
2724 bp += NFSX_UNSIGNED;
2725
2726 /* And loop around copying the name */
2727 xfer = nlen;
2728 cp = dp->d_name;
2729 while (xfer > 0) {
2730 nfsm_clget;
2731 if ((bp+xfer) > be)
2732 tsiz = be-bp;
2733 else
2734 tsiz = xfer;
2735 memcpy(bp, cp, tsiz);
2736 bp += tsiz;
2737 xfer -= tsiz;
2738 if (xfer > 0)
2739 cp += tsiz;
2740 }
2741 /* And null pad to an int32_t boundary */
2742 for (i = 0; i < rem; i++)
2743 *bp++ = '\0';
2744 nfsm_clget;
2745
2746 /* Finish off the record */
2747 txdr_hyper(*cookiep, &jar);
2748 if (v3) {
2749 *tl = jar.nfsuquad[0];
2750 bp += NFSX_UNSIGNED;
2751 nfsm_clget;
2752 }
2753 *tl = jar.nfsuquad[1];
2754 bp += NFSX_UNSIGNED;
2755 }
2756 cpos += dp->d_reclen;
2757 dp = (struct dirent *)cpos;
2758 cookiep++;
2759 ncookies--;
2760 }
2761 vrele(vp);
2762 nfsm_clget;
2763 *tl = nfs_false;
2764 bp += NFSX_UNSIGNED;
2765 nfsm_clget;
2766 if (eofflag)
2767 *tl = nfs_true;
2768 else
2769 *tl = nfs_false;
2770 bp += NFSX_UNSIGNED;
2771 if (mp != mb) {
2772 if (bp < be)
2773 mp->m_len = bp - mtod(mp, caddr_t);
2774 } else
2775 mp->m_len += bp - bpos;
2776 free((caddr_t)rbuf, M_TEMP);
2777 free((caddr_t)cookies, M_TEMP);
2778 nfsm_srvdone;
2779 }
2780
2781 int
2782 nfsrv_readdirplus(nfsd, slp, procp, mrq)
2783 struct nfsrv_descript *nfsd;
2784 struct nfssvc_sock *slp;
2785 struct proc *procp;
2786 struct mbuf **mrq;
2787 {
2788 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2789 struct mbuf *nam = nfsd->nd_nam;
2790 caddr_t dpos = nfsd->nd_dpos;
2791 struct ucred *cred = &nfsd->nd_cr;
2792 char *bp, *be;
2793 struct mbuf *mp;
2794 struct dirent *dp;
2795 caddr_t cp;
2796 u_int32_t *tl;
2797 int32_t t1;
2798 caddr_t bpos;
2799 struct mbuf *mb, *mreq, *mp2;
2800 char *cpos, *cend, *cp2, *rbuf;
2801 struct vnode *vp, *nvp;
2802 struct flrep fl;
2803 nfsfh_t nfh;
2804 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
2805 struct uio io;
2806 struct iovec iv;
2807 struct vattr va, at, *vap = &va;
2808 struct nfs_fattr *fp;
2809 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2810 int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
2811 u_quad_t frev, off, toff, verf;
2812 off_t *cookies = NULL, *cookiep;
2813
2814 fhp = &nfh.fh_generic;
2815 nfsm_srvmtofh(fhp);
2816 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2817 toff = fxdr_hyper(tl);
2818 tl += 2;
2819 verf = fxdr_hyper(tl);
2820 tl += 2;
2821 siz = fxdr_unsigned(int, *tl++);
2822 cnt = fxdr_unsigned(int, *tl);
2823 off = toff;
2824 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2825 xfer = NFS_SRVMAXDATA(nfsd);
2826 if (siz > xfer)
2827 siz = xfer;
2828 fullsiz = siz;
2829 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2830 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2831 if (!error && vp->v_type != VDIR) {
2832 error = ENOTDIR;
2833 vput(vp);
2834 }
2835 if (error) {
2836 nfsm_reply(NFSX_UNSIGNED);
2837 nfsm_srvpostop_attr(getret, &at);
2838 return (0);
2839 }
2840 error = getret = VOP_GETATTR(vp, &at, cred, procp);
2841 #ifdef NFS3_STRICTVERF
2842 /*
2843 * XXX This check is too strict for Solaris 2.5 clients.
2844 */
2845 if (!error && toff && verf != at.va_filerev)
2846 error = NFSERR_BAD_COOKIE;
2847 #endif
2848 if (!error) {
2849 nqsrv_getl(vp, ND_READ);
2850 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
2851 }
2852 if (error) {
2853 vput(vp);
2854 nfsm_reply(NFSX_V3POSTOPATTR);
2855 nfsm_srvpostop_attr(getret, &at);
2856 return (0);
2857 }
2858 VOP_UNLOCK(vp, 0);
2859
2860 rbuf = malloc(siz, M_TEMP, M_WAITOK);
2861 again:
2862 iv.iov_base = rbuf;
2863 iv.iov_len = fullsiz;
2864 io.uio_iov = &iv;
2865 io.uio_iovcnt = 1;
2866 io.uio_offset = (off_t)off;
2867 io.uio_resid = fullsiz;
2868 io.uio_segflg = UIO_SYSSPACE;
2869 io.uio_rw = UIO_READ;
2870 io.uio_procp = (struct proc *)0;
2871 eofflag = 0;
2872
2873 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2874
2875 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
2876
2877 off = (u_quad_t)io.uio_offset;
2878 getret = VOP_GETATTR(vp, &at, cred, procp);
2879
2880 VOP_UNLOCK(vp, 0);
2881
2882 /*
2883 * If the VGET operation doesn't work for this filesystem,
2884 * we can't support readdirplus. Returning NOTSUPP should
2885 * make clients fall back to plain readdir.
2886 * There's no need to check for VPTOFH as well, we wouldn't
2887 * even be here otherwise.
2888 */
2889 if (!getret) {
2890 if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, &nvp)))
2891 getret = (getret == EOPNOTSUPP) ?
2892 NFSERR_NOTSUPP : NFSERR_IO;
2893 else
2894 vput(nvp);
2895 }
2896
2897 if (!cookies && !error)
2898 error = NFSERR_PERM;
2899 if (!error)
2900 error = getret;
2901 if (error) {
2902 vrele(vp);
2903 if (cookies)
2904 free((caddr_t)cookies, M_TEMP);
2905 free((caddr_t)rbuf, M_TEMP);
2906 nfsm_reply(NFSX_V3POSTOPATTR);
2907 nfsm_srvpostop_attr(getret, &at);
2908 return (0);
2909 }
2910 if (io.uio_resid) {
2911 siz -= io.uio_resid;
2912
2913 /*
2914 * If nothing read, return eof
2915 * rpc reply
2916 */
2917 if (siz == 0) {
2918 vrele(vp);
2919 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
2920 2 * NFSX_UNSIGNED);
2921 nfsm_srvpostop_attr(getret, &at);
2922 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2923 txdr_hyper(at.va_filerev, tl);
2924 tl += 2;
2925 *tl++ = nfs_false;
2926 *tl = nfs_true;
2927 free((caddr_t)cookies, M_TEMP);
2928 free((caddr_t)rbuf, M_TEMP);
2929 return (0);
2930 }
2931 }
2932
2933 /*
2934 * Check for degenerate cases of nothing useful read.
2935 * If so go try again
2936 */
2937 cpos = rbuf;
2938 cend = rbuf + siz;
2939 dp = (struct dirent *)cpos;
2940 cookiep = cookies;
2941
2942 while (cpos < cend && ncookies > 0 &&
2943 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
2944 cpos += dp->d_reclen;
2945 dp = (struct dirent *)cpos;
2946 cookiep++;
2947 ncookies--;
2948 }
2949 if (cpos >= cend || ncookies == 0) {
2950 toff = off;
2951 siz = fullsiz;
2952 goto again;
2953 }
2954
2955 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
2956 nfsm_reply(cnt);
2957 nfsm_srvpostop_attr(getret, &at);
2958 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2959 txdr_hyper(at.va_filerev, tl);
2960 mp = mp2 = mb;
2961 bp = bpos;
2962 be = bp + M_TRAILINGSPACE(mp);
2963
2964 /* Loop through the records and build reply */
2965 while (cpos < cend && ncookies > 0) {
2966 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2967 nlen = dp->d_namlen;
2968 rem = nfsm_rndup(nlen)-nlen;
2969
2970 /*
2971 * For readdir_and_lookup get the vnode using
2972 * the file number.
2973 */
2974 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
2975 goto invalid;
2976 memset((caddr_t)nfhp, 0, NFSX_V3FH);
2977 nfhp->fh_fsid =
2978 nvp->v_mount->mnt_stat.f_fsid;
2979 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
2980 vput(nvp);
2981 goto invalid;
2982 }
2983 if (VOP_GETATTR(nvp, vap, cred, procp)) {
2984 vput(nvp);
2985 goto invalid;
2986 }
2987 vput(nvp);
2988
2989 /*
2990 * If either the dircount or maxcount will be
2991 * exceeded, get out now. Both of these lengths
2992 * are calculated conservatively, including all
2993 * XDR overheads.
2994 */
2995 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
2996 NFSX_V3POSTOPATTR);
2997 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
2998 if (len > cnt || dirlen > fullsiz) {
2999 eofflag = 0;
3000 break;
3001 }
3002
3003 /*
3004 * Build the directory record xdr from
3005 * the dirent entry.
3006 */
3007 fp = (struct nfs_fattr *)&fl.fl_fattr;
3008 nfsm_srvfillattr(vap, fp);
3009 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3010 fl.fl_fhok = nfs_true;
3011 fl.fl_postopok = nfs_true;
3012 txdr_hyper(*cookiep, fl.fl_off.nfsuquad);
3013
3014 nfsm_clget;
3015 *tl = nfs_true;
3016 bp += NFSX_UNSIGNED;
3017 nfsm_clget;
3018 *tl = 0;
3019 bp += NFSX_UNSIGNED;
3020 nfsm_clget;
3021 *tl = txdr_unsigned(dp->d_fileno);
3022 bp += NFSX_UNSIGNED;
3023 nfsm_clget;
3024 *tl = txdr_unsigned(nlen);
3025 bp += NFSX_UNSIGNED;
3026
3027 /* And loop around copying the name */
3028 xfer = nlen;
3029 cp = dp->d_name;
3030 while (xfer > 0) {
3031 nfsm_clget;
3032 if ((bp + xfer) > be)
3033 tsiz = be - bp;
3034 else
3035 tsiz = xfer;
3036 memcpy(bp, cp, tsiz);
3037 bp += tsiz;
3038 xfer -= tsiz;
3039 if (xfer > 0)
3040 cp += tsiz;
3041 }
3042 /* And null pad to an int32_t boundary */
3043 for (i = 0; i < rem; i++)
3044 *bp++ = '\0';
3045
3046 /*
3047 * Now copy the flrep structure out.
3048 */
3049 xfer = sizeof (struct flrep);
3050 cp = (caddr_t)&fl;
3051 while (xfer > 0) {
3052 nfsm_clget;
3053 if ((bp + xfer) > be)
3054 tsiz = be - bp;
3055 else
3056 tsiz = xfer;
3057 memcpy(bp, cp, tsiz);
3058 bp += tsiz;
3059 xfer -= tsiz;
3060 if (xfer > 0)
3061 cp += tsiz;
3062 }
3063 }
3064 invalid:
3065 cpos += dp->d_reclen;
3066 dp = (struct dirent *)cpos;
3067 cookiep++;
3068 ncookies--;
3069 }
3070 vrele(vp);
3071 nfsm_clget;
3072 *tl = nfs_false;
3073 bp += NFSX_UNSIGNED;
3074 nfsm_clget;
3075 if (eofflag)
3076 *tl = nfs_true;
3077 else
3078 *tl = nfs_false;
3079 bp += NFSX_UNSIGNED;
3080 if (mp != mb) {
3081 if (bp < be)
3082 mp->m_len = bp - mtod(mp, caddr_t);
3083 } else
3084 mp->m_len += bp - bpos;
3085 free((caddr_t)cookies, M_TEMP);
3086 free((caddr_t)rbuf, M_TEMP);
3087 nfsm_srvdone;
3088 }
3089
3090 /*
3091 * nfs commit service
3092 */
3093 int
3094 nfsrv_commit(nfsd, slp, procp, mrq)
3095 struct nfsrv_descript *nfsd;
3096 struct nfssvc_sock *slp;
3097 struct proc *procp;
3098 struct mbuf **mrq;
3099 {
3100 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3101 struct mbuf *nam = nfsd->nd_nam;
3102 caddr_t dpos = nfsd->nd_dpos;
3103 struct ucred *cred = &nfsd->nd_cr;
3104 struct vattr bfor, aft;
3105 struct vnode *vp;
3106 nfsfh_t nfh;
3107 fhandle_t *fhp;
3108 u_int32_t *tl;
3109 int32_t t1;
3110 caddr_t bpos;
3111 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
3112 char *cp2;
3113 struct mbuf *mb, *mreq;
3114 u_quad_t frev, off, end;
3115
3116 #ifndef nolint
3117 cache = 0;
3118 #endif
3119 fhp = &nfh.fh_generic;
3120 nfsm_srvmtofh(fhp);
3121 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3122
3123 off = fxdr_hyper(tl);
3124 tl += 2;
3125 cnt = fxdr_unsigned(int, *tl);
3126 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3127 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3128 if (error) {
3129 nfsm_reply(2 * NFSX_UNSIGNED);
3130 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3131 return (0);
3132 }
3133 for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
3134 end = (cnt > 0) ? off + cnt : vp->v_size;
3135 if (end < off || end > vp->v_size)
3136 end = vp->v_size;
3137 error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end, procp);
3138 aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
3139 vput(vp);
3140 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3141 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3142 if (!error) {
3143 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
3144 *tl++ = txdr_unsigned(boottime.tv_sec);
3145 *tl = txdr_unsigned(boottime.tv_usec);
3146 } else
3147 return (0);
3148 nfsm_srvdone;
3149 }
3150
3151 /*
3152 * nfs statfs service
3153 */
3154 int
3155 nfsrv_statfs(nfsd, slp, procp, mrq)
3156 struct nfsrv_descript *nfsd;
3157 struct nfssvc_sock *slp;
3158 struct proc *procp;
3159 struct mbuf **mrq;
3160 {
3161 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3162 struct mbuf *nam = nfsd->nd_nam;
3163 caddr_t dpos = nfsd->nd_dpos;
3164 struct ucred *cred = &nfsd->nd_cr;
3165 struct statfs *sf;
3166 struct nfs_statfs *sfp;
3167 u_int32_t *tl;
3168 int32_t t1;
3169 caddr_t bpos;
3170 int error = 0, rdonly, cache, getret = 1;
3171 int v3 = (nfsd->nd_flag & ND_NFSV3);
3172 char *cp2;
3173 struct mbuf *mb, *mreq;
3174 struct vnode *vp;
3175 struct vattr at;
3176 nfsfh_t nfh;
3177 fhandle_t *fhp;
3178 struct statfs statfs;
3179 u_quad_t frev, tval;
3180
3181 #ifndef nolint
3182 cache = 0;
3183 #endif
3184 fhp = &nfh.fh_generic;
3185 nfsm_srvmtofh(fhp);
3186 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3187 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3188 if (error) {
3189 nfsm_reply(NFSX_UNSIGNED);
3190 nfsm_srvpostop_attr(getret, &at);
3191 return (0);
3192 }
3193 sf = &statfs;
3194 error = VFS_STATFS(vp->v_mount, sf, procp);
3195 getret = VOP_GETATTR(vp, &at, cred, procp);
3196 vput(vp);
3197 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3198 if (v3)
3199 nfsm_srvpostop_attr(getret, &at);
3200 if (error)
3201 return (0);
3202 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
3203 if (v3) {
3204 tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_bsize);
3205 txdr_hyper(tval, &sfp->sf_tbytes);
3206 tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_bsize);
3207 txdr_hyper(tval, &sfp->sf_fbytes);
3208 tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_bsize);
3209 txdr_hyper(tval, &sfp->sf_abytes);
3210 tval = (u_quad_t)sf->f_files;
3211 txdr_hyper(tval, &sfp->sf_tfiles);
3212 tval = (u_quad_t)sf->f_ffree;
3213 txdr_hyper(tval, &sfp->sf_ffiles);
3214 txdr_hyper(tval, &sfp->sf_afiles);
3215 sfp->sf_invarsec = 0;
3216 } else {
3217 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3218 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3219 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3220 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3221 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3222 }
3223 nfsm_srvdone;
3224 }
3225
3226 /*
3227 * nfs fsinfo service
3228 */
3229 int
3230 nfsrv_fsinfo(nfsd, slp, procp, mrq)
3231 struct nfsrv_descript *nfsd;
3232 struct nfssvc_sock *slp;
3233 struct proc *procp;
3234 struct mbuf **mrq;
3235 {
3236 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3237 struct mbuf *nam = nfsd->nd_nam;
3238 caddr_t dpos = nfsd->nd_dpos;
3239 struct ucred *cred = &nfsd->nd_cr;
3240 u_int32_t *tl;
3241 struct nfsv3_fsinfo *sip;
3242 int32_t t1;
3243 caddr_t bpos;
3244 int error = 0, rdonly, cache, getret = 1;
3245 uint32_t maxdata;
3246 char *cp2;
3247 struct mbuf *mb, *mreq;
3248 struct vnode *vp;
3249 struct vattr at;
3250 nfsfh_t nfh;
3251 fhandle_t *fhp;
3252 u_quad_t frev, maxfsize;
3253 struct statfs sb;
3254
3255 #ifndef nolint
3256 cache = 0;
3257 #endif
3258 fhp = &nfh.fh_generic;
3259 nfsm_srvmtofh(fhp);
3260 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3261 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3262 if (error) {
3263 nfsm_reply(NFSX_UNSIGNED);
3264 nfsm_srvpostop_attr(getret, &at);
3265 return (0);
3266 }
3267
3268 /* XXX Try to make a guess on the max file size. */
3269 VFS_STATFS(vp->v_mount, &sb, (struct proc *)0);
3270 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3271
3272 getret = VOP_GETATTR(vp, &at, cred, procp);
3273 vput(vp);
3274 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3275 nfsm_srvpostop_attr(getret, &at);
3276 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3277
3278 /*
3279 * XXX
3280 * There should be file system VFS OP(s) to get this information.
3281 * For now, assume ufs.
3282 */
3283 if (slp->ns_so->so_type == SOCK_DGRAM)
3284 maxdata = NFS_MAXDGRAMDATA;
3285 else
3286 maxdata = NFS_MAXDATA;
3287 sip->fs_rtmax = txdr_unsigned(maxdata);
3288 sip->fs_rtpref = txdr_unsigned(maxdata);
3289 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3290 sip->fs_wtmax = txdr_unsigned(maxdata);
3291 sip->fs_wtpref = txdr_unsigned(maxdata);
3292 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3293 sip->fs_dtpref = txdr_unsigned(maxdata);
3294 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3295 sip->fs_timedelta.nfsv3_sec = 0;
3296 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3297 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3298 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3299 NFSV3FSINFO_CANSETTIME);
3300 nfsm_srvdone;
3301 }
3302
3303 /*
3304 * nfs pathconf service
3305 */
3306 int
3307 nfsrv_pathconf(nfsd, slp, procp, mrq)
3308 struct nfsrv_descript *nfsd;
3309 struct nfssvc_sock *slp;
3310 struct proc *procp;
3311 struct mbuf **mrq;
3312 {
3313 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3314 struct mbuf *nam = nfsd->nd_nam;
3315 caddr_t dpos = nfsd->nd_dpos;
3316 struct ucred *cred = &nfsd->nd_cr;
3317 u_int32_t *tl;
3318 struct nfsv3_pathconf *pc;
3319 int32_t t1;
3320 caddr_t bpos;
3321 int error = 0, rdonly, cache, getret = 1;
3322 register_t linkmax, namemax, chownres, notrunc;
3323 char *cp2;
3324 struct mbuf *mb, *mreq;
3325 struct vnode *vp;
3326 struct vattr at;
3327 nfsfh_t nfh;
3328 fhandle_t *fhp;
3329 u_quad_t frev;
3330
3331 #ifndef nolint
3332 cache = 0;
3333 #endif
3334 fhp = &nfh.fh_generic;
3335 nfsm_srvmtofh(fhp);
3336 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3337 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3338 if (error) {
3339 nfsm_reply(NFSX_UNSIGNED);
3340 nfsm_srvpostop_attr(getret, &at);
3341 return (0);
3342 }
3343 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3344 if (!error)
3345 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3346 if (!error)
3347 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3348 if (!error)
3349 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
3350 getret = VOP_GETATTR(vp, &at, cred, procp);
3351 vput(vp);
3352 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3353 nfsm_srvpostop_attr(getret, &at);
3354 if (error)
3355 return (0);
3356 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3357
3358 pc->pc_linkmax = txdr_unsigned(linkmax);
3359 pc->pc_namemax = txdr_unsigned(namemax);
3360 pc->pc_notrunc = txdr_unsigned(notrunc);
3361 pc->pc_chownrestricted = txdr_unsigned(chownres);
3362
3363 /*
3364 * These should probably be supported by VOP_PATHCONF(), but
3365 * until msdosfs is exportable (why would you want to?), the
3366 * Unix defaults should be ok.
3367 */
3368 pc->pc_caseinsensitive = nfs_false;
3369 pc->pc_casepreserving = nfs_true;
3370 nfsm_srvdone;
3371 }
3372
3373 /*
3374 * Null operation, used by clients to ping server
3375 */
3376 /* ARGSUSED */
3377 int
3378 nfsrv_null(nfsd, slp, procp, mrq)
3379 struct nfsrv_descript *nfsd;
3380 struct nfssvc_sock *slp;
3381 struct proc *procp;
3382 struct mbuf **mrq;
3383 {
3384 struct mbuf *mrep = nfsd->nd_mrep;
3385 caddr_t bpos;
3386 int error = NFSERR_RETVOID, cache = 0;
3387 struct mbuf *mb, *mreq;
3388 u_quad_t frev;
3389
3390 nfsm_reply(0);
3391 return (0);
3392 }
3393
3394 /*
3395 * No operation, used for obsolete procedures
3396 */
3397 /* ARGSUSED */
3398 int
3399 nfsrv_noop(nfsd, slp, procp, mrq)
3400 struct nfsrv_descript *nfsd;
3401 struct nfssvc_sock *slp;
3402 struct proc *procp;
3403 struct mbuf **mrq;
3404 {
3405 struct mbuf *mrep = nfsd->nd_mrep;
3406 caddr_t bpos;
3407 int error, cache = 0;
3408 struct mbuf *mb, *mreq;
3409 u_quad_t frev;
3410
3411 if (nfsd->nd_repstat)
3412 error = nfsd->nd_repstat;
3413 else
3414 error = EPROCUNAVAIL;
3415 nfsm_reply(0);
3416 return (0);
3417 }
3418
3419 /*
3420 * Perform access checking for vnodes obtained from file handles that would
3421 * refer to files already opened by a Unix client. You cannot just use
3422 * vn_writechk() and VOP_ACCESS() for two reasons.
3423 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3424 * 2 - The owner is to be given access irrespective of mode bits for some
3425 * operations, so that processes that chmod after opening a file don't
3426 * break. I don't like this because it opens a security hole, but since
3427 * the nfs server opens a security hole the size of a barn door anyhow,
3428 * what the heck.
3429 *
3430 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3431 * will return EPERM instead of EACCESS. EPERM is always an error.
3432 */
3433 int
3434 nfsrv_access(vp, flags, cred, rdonly, p, override)
3435 struct vnode *vp;
3436 int flags;
3437 struct ucred *cred;
3438 int rdonly;
3439 struct proc *p;
3440 {
3441 struct vattr vattr;
3442 int error;
3443 if (flags & VWRITE) {
3444 /* Just vn_writechk() changed to check rdonly */
3445 /*
3446 * Disallow write attempts on read-only file systems;
3447 * unless the file is a socket or a block or character
3448 * device resident on the file system.
3449 */
3450 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3451 switch (vp->v_type) {
3452 case VREG:
3453 case VDIR:
3454 case VLNK:
3455 return (EROFS);
3456 default:
3457 break;
3458 }
3459 }
3460
3461 /*
3462 * If the vnode is in use as a process's text,
3463 * we can't allow writing.
3464 */
3465 if (vp->v_flag & VTEXT)
3466 return (ETXTBSY);
3467 }
3468 error = VOP_GETATTR(vp, &vattr, cred, p);
3469 if (error)
3470 return (error);
3471 error = VOP_ACCESS(vp, flags, cred, p);
3472 /*
3473 * Allow certain operations for the owner (reads and writes
3474 * on files that are already open).
3475 */
3476 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3477 error = 0;
3478 return error;
3479 }
3480