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